This commit is contained in:
Simon Kellet 2025-02-26 17:14:52 +00:00
parent 475df14a52
commit ca8d1893db
6 changed files with 238 additions and 0 deletions

1
libs/odin-curl Submodule

@ -0,0 +1 @@
Subproject commit cf072c11233c1226b0ccfcb65fa9d93224de8e01

84
main.odin Normal file
View File

@ -0,0 +1,84 @@
package main
import curl "./libs/odin-curl/"
import "core:encoding/json"
import "core:flags"
import "core:fmt"
import "core:mem"
import vmem "core:mem/virtual"
import "core:os"
import "core:strings"
import "core:time"
HOST :: "https://api.openweathermap.org/data/2.5/weather?q="
main :: proc() {
arena: vmem.Arena
arena_err := vmem.arena_init_growing(&arena)
ensure(arena_err == nil) //make sure it doesnt fuck up
arena_alloc := vmem.arena_allocator(&arena)
defer vmem.arena_destroy(&arena) //clean up at end
city := "" //city name e.g. London
code := "" //code e.g. UK, JP, GE
api_key := "" //openweather api key
sb := strings.builder_make(allocator = arena_alloc)
buf1: [64]u8
buf2: [64]u8
// parse os.args in this order
// city -> code -> api_key
program_name := os.args[0]
if len(os.args) < 3 {
print_usage()
} else if len(os.args) > 4 {
print_usage()
}
city = os.args[1]
code = os.args[2]
api_key = os.args[3]
strings.write_string(&sb, HOST)
strings.write_string(&sb, city)
strings.write_string(&sb, ",")
strings.write_string(&sb, code)
strings.write_string(&sb, "&units=metric")
strings.write_string(&sb, "&appid=")
strings.write_string(&sb, api_key)
full_url := strings.to_string(sb)
data := curl_web(full_url)
weather: WeatherResponse
unmarshal_err := json.unmarshal_any(data, &weather)
if unmarshal_err != nil {
fmt.eprintln("Failed to unmarshal the file!")
return
}
weather_location := weather.name
weather_code := weather.sys.country
weather_resp := weather.weather[0].main
weather_resp_detail := weather.weather[0].description
//weather_icon := weather.weather[0].icon
temperature := weather.main.temp
feels_like_temp := weather.main.feels_like
temp_min := weather.main.temp_min
temp_max := weather.main.temp_max
sunset_time := time.to_string_hms_12(time.unix(weather.sys.sunset, 0), buf1[:])
sunrise_time := time.to_string_hms_12(time.unix(weather.sys.sunrise, 0), buf2[:])
fmt.println("Location:", weather_location)
fmt.println("Country Code:", weather_code)
fmt.println("Weather:", weather_resp)
fmt.println("Weather Detail:", weather_resp_detail)
//fmt.println("Weather Icon:", weather_icon)
fmt.println("Temperature:", temperature)
fmt.println("Feels Like Temperature:", feels_like_temp)
fmt.println("Min Temperature:", temp_min)
fmt.println("Max Temperature:", temp_max)
fmt.println("Sunset Time:", sunset_time)
fmt.println("Sunrise Time:", sunrise_time)
}

32
test.json Normal file
View File

@ -0,0 +1,32 @@
[
{
"arrival": "2025-01-01",
"departure": "2025-01-16",
"name": "John Doe",
"reference": "GFYHD4"
},
{
"arrival": "2025-03-01",
"departure": "2025-03-04",
"name": "Jonathan Davis",
"reference": "TRICQ23"
},
{
"arrival": "2025-01-15",
"departure": "2025-01-18",
"name": "Daniel Dumile",
"reference": "YH74H1"
},
{
"arrival": "2025-02-05",
"departure": "2025-02-15",
"name": "Nasir Jones",
"reference": "XNASL2"
},
{
"arrival": "2025-02-15",
"departure": "2025-02-21",
"name": "Adam Carter",
"reference": "93TILIN"
}
]

61
util.odin Normal file
View File

@ -0,0 +1,61 @@
package main
import curl "./libs/odin-curl/"
import "base:runtime"
import "core:encoding/json"
import "core:fmt"
import "core:mem"
import vmem "core:mem/virtual"
import "core:os"
import "core:unicode/utf8"
print_usage :: proc() {
fmt.printf("Usage:\n\t%s [city] [code] [api_key] \n", os.args[0])
os.exit(1)
}
DataContext :: struct {
data: []byte,
ctx: runtime.Context,
}
curl_web :: proc(url: string) -> []u8 {
using curl
h := easy_init()
defer easy_cleanup(h)
headers: ^curl_slist
headers = slist_append(nil, "content-type: application/json")
headers = slist_append(headers, "Accept: application/json")
headers = slist_append(headers, "charset: utf-8")
defer slist_free_all(headers)
easy_setopt(h, CURLoption.URL, url)
hres := easy_setopt(h, CURLoption.HTTPHEADER, headers)
// Verify option was set correctly:
if hres != CURLcode.OK {
fmt.println("Failed to set HTTPHEADER: ", easy_strerror(hres))
}
easy_setopt(h, CURLoption.WRITEFUNCTION, write_callback)
data := DataContext{nil, context}
easy_setopt(h, .WRITEDATA, &data)
result := easy_perform(h)
if result != CURLcode.OK {
fmt.println("Error occurred: ", result)
}
return data.data
}
write_callback :: proc "c" (contents: rawptr, size: uint, nmemb: uint, userp: rawptr) -> uint {
dc := transmute(^DataContext)userp
context = dc.ctx
total_size := size * nmemb
content_str := transmute([^]u8)contents
dc.data = make([]byte, int(total_size)) // <-- ALLOCATION
mem.copy(&dc.data[0], content_str, int(total_size))
return total_size
}

BIN
weather Executable file

Binary file not shown.

60
weather.odin Normal file
View File

@ -0,0 +1,60 @@
package main
Clouds :: struct {
all: f32,
}
Sys :: struct {
sunrise: i64,
sunset: i64,
country: string,
}
Coord :: struct {
lon: f32,
lat: f32,
}
Weather :: struct {
id: int,
main: string,
icon: string,
description: string,
}
Main :: struct {
temp_min: f32,
feels_like: f32,
pressure: int,
temp_max: f32,
temp: f32,
humidity: int,
sea_level: int,
grnd_level: int,
}
Wind :: struct {
gust: f32,
speed: f32,
deg: int,
}
Visibility :: struct {
visibility: int,
}
WeatherResponse :: struct {
clouds: Clouds,
sys: Sys,
name: string,
base: string,
coord: Coord,
timezone: int,
weather: []Weather,
main: Main,
visibility: int,
dt: f64,
id: int,
wind: Wind,
cod: int,
}