import std/[json, httpclient, sequtils, strformat, strutils] type Station = object id: string name: string type Departure = ref object destination: string color: string estimates: seq[uint] proc newStation(id: string, name: string): Station = Station(id: id, name: name) const bart_stations = @[ newStation("12th", "12th St. Oakland City Center"), newStation("16th", "16th St. Mission (SF)"), newStation("19th", "19th St. Oakland"), newStation("24th", "24th St. Mission (SF)"), newStation("ashb", "Ashby (Berkeley)"), newStation("antc", "Antioch"), newStation("balb", "Balboa Park (SF)"), newStation("bayf", "Bay Fair (San Leandro)"), newStation("bery", "Berryessa / North San Jose"), newStation("cast", "Castro Valley"), newStation("civc", "Civic Center (SF)"), newStation("cols", "Coliseum"), newStation("colm", "Colma"), newStation("conc", "Concord"), newStation("daly", "Daly City"), newStation("dbrk", "Downtown Berkeley"), newStation("dubl", "Dublin/Pleasanton"), newStation("deln", "El Cerrito del Norte"), newStation("plza", "El Cerrito Plaza"), newStation("embr", "Embarcadero (SF)"), newStation("frmt", "Fremont"), newStation("ftvl", "Fruitvale (Oakland)"), newStation("glen", "Glen Park (SF)"), newStation("hayw", "Hayward"), newStation("lafy", "Lafayette"), newStation("lake", "Lake Merritt (Oakland)"), newStation("mcar", "MacArthur (Oakland)"), newStation("mlbr", "Millbrae"), newStation("mlpt", "Milpitas"), newStation("mont", "Montgomery St. (SF)"), newStation("nbrk", "North Berkeley"), newStation("ncon", "North Concord/Martinez"), newStation("oakl", "Oakland Int'l Airport"), newStation("orin", "Orinda"), newStation("pitt", "Pittsburg/Bay Point"), newStation("pctr", "Pittsburg Center"), newStation("phil", "Pleasant Hill"), newStation("powl", "Powell St. (SF)"), newStation("rich", "Richmond"), newStation("rock", "Rockridge (Oakland)"), newStation("sbrn", "San Bruno"), newStation("sfia", "San Francisco Int'l Airport"), newStation("sanl", "San Leandro"), newStation("shay", "South Hayward"), newStation("ssan", "South San Francisco"), newStation("ucty", "Union City"), newStation("warm", "Warm Springs/South Fremont"), newStation("wcrk", "Walnut Creek"), newStation("wdub", "West Dublin"), newStation("woak", "West Oakland"), ] proc bart_station_names*(): seq[string] = bart_stations.map(proc(s: Station): string = s.name) proc get_departures(client: HTTPClient, station: Station): JSONNode = let id = station.id let response = client.get(&"http://api.bart.gov/api/etd.aspx?cmd=etd&orig={id}&key=MW9S-E7SL-26DU-VV8V&json=y") parseJSON(response.body) proc format_estimate_minutes(minutes: string): uint = case minutes: of "Leaving": return 0.uint else: return parseUInt(minutes) proc parse_departures(etd: JSONNode): seq[Departure] = if not etd["root"].hasKey("station"): return @[] let lines = etd["root"]["station"][0]["etd"].getElems lines.map(proc (line: JSONNode): Departure = let dest = line["destination"].getStr let color = line["estimate"][0]["color"].getStr let estimates = line["estimate"].getElems.map(proc(estimate: JSONNode): uint = format_estimate_minutes(estimate["minutes"].getStr) ) Departure(destination: dest, color: color, estimates: estimates) ) proc format_departures(departures: seq[Departure]): string = departures.map(proc (d: Departure): string = let estimates = d.estimates.join(", ") &"{d.destination}\t{estimates}" ).join("\n") proc prediction_for_station_idx*(client: HTTPClient, idx: int): string = let station = bart_stations[idx] client.get_departures(station).parse_departures().format_departures()