Heads-I-Lose

Hex Artifact Content
Login

Artifact 06c428174b0c19d8bb515d0f0b2835bc226dc10f672825a0429402abe6be665b:


0000: 2d 6d 6f 64 75 6c 65 28 68 65 61 64 73 69 6c 6f  -module(headsilo
0010: 73 65 29 2e 0a 2d 65 78 70 6f 72 74 28 5b 67 65  se)..-export([ge
0020: 74 5f 6c 6f 63 61 74 69 6f 6e 73 2f 30 2c 20 67  t_locations/0, g
0030: 65 74 5f 6c 6f 63 61 74 69 6f 6e 73 2f 31 2c 20  et_locations/1, 
0040: 68 65 61 64 73 69 6c 6f 73 65 2f 31 5d 29 2e 0a  headsilose/1])..
0050: 2d 69 6e 63 6c 75 64 65 5f 6c 69 62 28 22 78 6d  -include_lib("xm
0060: 65 72 6c 2f 69 6e 63 6c 75 64 65 2f 78 6d 65 72  erl/include/xmer
0070: 6c 2e 68 72 6c 22 29 2e 0a 2d 69 6d 70 6f 72 74  l.hrl")..-import
0080: 28 77 65 61 74 68 65 72 5f 74 79 70 65 73 2c 20  (weather_types, 
0090: 5b 77 65 61 74 68 65 72 5f 74 79 70 65 2f 31 5d  [weather_type/1]
00a0: 29 2e 0a 2d 69 6d 70 6f 72 74 28 70 6f 6c 79 6c  )..-import(polyl
00b0: 69 6e 65 2c 20 5b 64 65 63 6f 64 65 2f 31 5d 29  ine, [decode/1])
00c0: 2e 0a 2d 69 6d 70 6f 72 74 28 6f 73 72 6d 2c 20  ..-import(osrm, 
00d0: 5b 72 65 61 64 5f 72 6f 75 74 65 2f 31 5d 29 2e  [read_route/1]).
00e0: 0a 0a 25 53 75 70 70 6c 79 20 61 20 64 69 72 65  ..%Supply a dire
00f0: 63 74 69 6f 6e 20 61 6e 64 20 6c 6f 63 61 74 69  ction and locati
0100: 6f 6e 20 61 6e 64 20 77 6f 72 6b 20 6f 75 74 20  on and work out 
0110: 69 66 20 68 65 61 64 20 77 69 6e 64 20 6f 72 20  if head wind or 
0120: 6e 6f 74 0a 25 46 6f 72 20 6e 6f 77 20 22 6b 6e  not.%For now "kn
0130: 6f 77 20 74 68 65 20 6c 6f 63 61 74 69 6f 6e 20  ow the location 
0140: 69 64 22 20 75 70 66 72 6f 6e 74 2c 20 62 75 74  id" upfront, but
0150: 20 69 64 65 61 6c 6c 79 20 6e 65 65 64 20 74 6f   ideally need to
0160: 20 73 65 61 72 63 68 20 66 6f 72 20 69 74 20 61   search for it a
0170: 74 20 73 6f 6d 65 20 70 6f 69 6e 74 20 6f 72 20  t some point or 
0180: 70 72 65 73 65 6e 74 20 61 20 63 68 6f 69 63 65  present a choice
0190: 2e 0a 0a 25 49 6e 69 74 69 61 6c 6c 79 20 62 61  ...%Initially ba
01a0: 73 65 64 20 6f 6e 3a 20 68 74 74 70 3a 2f 2f 70  sed on: http://p
01b0: 72 61 67 64 61 76 65 2e 70 72 61 67 70 72 6f 67  ragdave.pragprog
01c0: 2e 63 6f 6d 2f 70 72 61 67 64 61 76 65 2f 32 30  .com/pragdave/20
01d0: 30 37 2f 30 34 2f 61 5f 66 69 72 73 74 5f 65 72  07/04/a_first_er
01e0: 6c 61 6e 67 5f 2e 68 74 6d 6c 0a 0a 2d 64 65 66  lang_.html..-def
01f0: 69 6e 65 28 42 41 53 45 5f 55 52 4c 2c 0a 09 22  ine(BASE_URL,.."
0200: 68 74 74 70 3a 2f 2f 64 61 74 61 70 6f 69 6e 74  http://datapoint
0210: 2e 6d 65 74 6f 66 66 69 63 65 2e 67 6f 76 2e 75  .metoffice.gov.u
0220: 6b 2f 70 75 62 6c 69 63 2f 64 61 74 61 2f 22 29  k/public/data/")
0230: 2e 0a 0a 2d 64 65 66 69 6e 65 28 57 58 46 43 53  ...-define(WXFCS
0240: 5f 53 49 54 45 4c 49 53 54 2c 0a 09 22 76 61 6c  _SITELIST,.."val
0250: 2f 77 78 66 63 73 2f 61 6c 6c 2f 78 6d 6c 2f 73  /wxfcs/all/xml/s
0260: 69 74 65 6c 69 73 74 22 29 2e 0a 0a 2d 64 65 66  itelist")...-def
0270: 69 6e 65 28 57 58 46 43 53 5f 4c 4f 43 41 54 49  ine(WXFCS_LOCATI
0280: 4f 4e 49 44 2c 0a 09 22 76 61 6c 2f 77 78 66 63  ONID,.."val/wxfc
0290: 73 2f 61 6c 6c 2f 78 6d 6c 2f 22 29 2e 0a 0a 0a  s/all/xml/")....
02a0: 25 46 69 72 73 74 20 6f 6e 65 20 66 6f 72 20 63  %First one for c
02b0: 6f 6d 6d 61 6e 64 20 6c 69 6e 65 20 75 73 61 67  ommand line usag
02c0: 65 0a 67 65 74 5f 6c 6f 63 61 74 69 6f 6e 73 28  e.get_locations(
02d0: 5b 53 65 61 72 63 68 5d 29 20 2d 3e 0a 09 67 65  [Search]) ->..ge
02e0: 74 5f 6c 6f 63 61 74 69 6f 6e 73 28 53 65 61 72  t_locations(Sear
02f0: 63 68 29 3b 0a 67 65 74 5f 6c 6f 63 61 74 69 6f  ch);.get_locatio
0300: 6e 73 28 53 65 61 72 63 68 29 20 2d 3e 0a 09 67  ns(Search) ->..g
0310: 65 74 5f 6c 6f 63 61 74 69 6f 6e 73 5f 28 22 2f  et_locations_("/
0320: 2f 4c 6f 63 61 74 69 6f 6e 5b 63 6f 6e 74 61 69  /Location[contai
0330: 6e 73 28 40 6e 61 6d 65 2c 20 27 22 2b 2b 53 65  ns(@name, '"++Se
0340: 61 72 63 68 2b 2b 22 27 29 5d 22 29 2e 0a 67 65  arch++"')]")..ge
0350: 74 5f 6c 6f 63 61 74 69 6f 6e 73 28 29 20 2d 3e  t_locations() ->
0360: 0a 09 67 65 74 5f 6c 6f 63 61 74 69 6f 6e 73 5f  ..get_locations_
0370: 28 22 2f 2f 4c 6f 63 61 74 69 6f 6e 22 29 2e 0a  ("//Location")..
0380: 67 65 74 5f 6c 6f 63 61 74 69 6f 6e 73 5f 28 58  get_locations_(X
0390: 70 61 74 68 29 20 2d 3e 0a 09 69 6e 65 74 73 3a  path) ->..inets:
03a0: 73 74 61 72 74 28 29 2c 0a 09 4b 65 79 20 3d 20  start(),..Key = 
03b0: 72 65 61 64 61 70 69 6b 65 79 28 29 2c 0a 09 55  readapikey(),..U
03c0: 52 4c 20 3d 20 3f 42 41 53 45 5f 55 52 4c 20 2b  RL = ?BASE_URL +
03d0: 2b 20 3f 57 58 46 43 53 5f 53 49 54 45 4c 49 53  + ?WXFCS_SITELIS
03e0: 54 20 2b 2b 20 22 3f 6b 65 79 3d 22 20 2b 2b 20  T ++ "?key=" ++ 
03f0: 4b 65 79 2c 0a 09 74 72 79 0a 09 09 25 48 61 6e  Key,..try...%Han
0400: 64 6c 69 6e 67 20 74 69 6d 65 6f 75 74 73 3a 20  dling timeouts: 
0410: 68 74 74 70 3a 2f 2f 73 74 61 63 6b 6f 76 65 72  http://stackover
0420: 66 6c 6f 77 2e 63 6f 6d 2f 61 2f 31 34 31 34 33  flow.com/a/14143
0430: 37 36 32 2f 32 30 38 37 39 33 0a 09 09 7b 20 6f  762/208793...{ o
0440: 6b 2c 20 7b 5f 53 74 61 74 75 73 2c 20 5f 48 65  k, {_Status, _He
0450: 61 64 65 72 73 2c 20 42 6f 64 79 20 7d 7d 20 3d  aders, Body }} =
0460: 20 68 74 74 70 63 3a 72 65 71 75 65 73 74 28 67   httpc:request(g
0470: 65 74 2c 20 7b 55 52 4c 2c 20 5b 5d 7d 2c 20 5b  et, {URL, []}, [
0480: 7b 74 69 6d 65 6f 75 74 2c 20 74 69 6d 65 72 3a  {timeout, timer:
0490: 73 65 63 6f 6e 64 73 28 31 30 29 7d 5d 2c 20 5b  seconds(10)}], [
04a0: 5d 29 2c 0a 09 09 7b 20 58 6d 6c 2c 20 5f 52 65  ]),...{ Xml, _Re
04b0: 73 74 20 7d 20 3d 20 78 6d 65 72 6c 5f 73 63 61  st } = xmerl_sca
04c0: 6e 3a 73 74 72 69 6e 67 28 42 6f 64 79 29 2c 0a  n:string(Body),.
04d0: 09 09 25 50 72 69 6e 74 20 61 20 6c 69 73 74 20  ..%Print a list 
04e0: 6f 66 20 4c 6f 63 61 74 69 6f 6e 73 20 61 6e 64  of Locations and
04f0: 20 49 44 73 0a 09 09 70 72 69 6e 74 5f 6c 6f 63   IDs...print_loc
0500: 61 74 69 6f 6e 73 28 78 6d 65 72 6c 5f 78 70 61  ations(xmerl_xpa
0510: 74 68 3a 73 74 72 69 6e 67 28 58 70 61 74 68 2c  th:string(Xpath,
0520: 20 58 6d 6c 29 29 0a 09 09 25 53 74 72 69 63 74   Xml))...%Strict
0530: 6c 79 20 73 70 65 61 6b 69 6e 67 20 74 68 69 73  ly speaking this
0540: 20 66 75 6e 63 74 69 6f 6e 20 73 68 6f 75 6c 64   function should
0550: 6e 27 74 20 62 65 20 68 65 72 65 20 61 73 20 69  n't be here as i
0560: 74 27 73 20 72 65 63 75 72 73 69 76 65 0a 09 09  t's recursive...
0570: 25 62 75 74 20 67 65 74 5f 6c 6f 63 61 74 69 6f  %but get_locatio
0580: 6e 73 20 69 73 20 61 20 72 75 6e 20 6f 6e 63 65  ns is a run once
0590: 20 66 75 6e 63 74 69 6f 6e 20 73 6f 20 49 20 74   function so I t
05a0: 68 69 6e 6b 20 69 74 27 73 20 6f 6b 0a 09 09 25  hink it's ok...%
05b0: 53 65 65 20 6e 6f 74 65 20 61 62 6f 76 65 20 68  See note above h
05c0: 74 74 70 3a 2f 2f 6c 65 61 72 6e 79 6f 75 73 6f  ttp://learnyouso
05d0: 6d 65 65 72 6c 61 6e 67 2e 63 6f 6d 2f 65 72 72  meerlang.com/err
05e0: 6f 72 73 2d 61 6e 64 2d 65 78 63 65 70 74 69 6f  ors-and-exceptio
05f0: 6e 73 23 74 68 65 72 65 73 2d 6d 6f 72 65 0a 09  ns#theres-more..
0600: 63 61 74 63 68 0a 09 09 5f 3a 52 65 61 73 6f 6e  catch..._:Reason
0610: 20 2d 3e 0a 09 09 09 69 6f 3a 66 6f 72 6d 61 74   ->....io:format
0620: 28 22 41 50 49 20 4d 69 67 68 74 20 62 65 20 64  ("API Might be d
0630: 6f 77 6e 7e 6e 22 29 2c 0a 09 09 09 52 65 61 73  own~n"),....Reas
0640: 6f 6e 0a 09 61 66 74 65 72 0a 09 09 6d 61 79 62  on..after...mayb
0650: 65 5f 71 75 69 74 28 29 0a 09 65 6e 64 2e 0a 0a  e_quit()..end...
0660: 0a 25 42 61 73 65 64 20 6f 6e 20 68 74 74 70 3a  .%Based on http:
0670: 2f 2f 69 6e 74 65 72 74 77 69 6e 67 6c 79 2e 6e  //intertwingly.n
0680: 65 74 2f 62 6c 6f 67 2f 32 30 30 37 2f 30 38 2f  et/blog/2007/08/
0690: 32 38 2f 50 61 72 73 69 6e 67 2d 41 74 6f 6d 2d  28/Parsing-Atom-
06a0: 77 69 74 68 2d 45 72 6c 61 6e 67 0a 70 72 69 6e  with-Erlang.prin
06b0: 74 5f 6c 6f 63 61 74 69 6f 6e 73 28 5b 5d 29 20  t_locations([]) 
06c0: 2d 3e 0a 09 65 6e 64 5f 6f 66 5f 6c 69 73 74 3b  ->..end_of_list;
06d0: 0a 70 72 69 6e 74 5f 6c 6f 63 61 74 69 6f 6e 73  .print_locations
06e0: 28 5b 4e 6f 64 65 7c 52 65 73 74 5d 29 20 2d 3e  ([Node|Rest]) ->
06f0: 0a 09 25 4e 65 65 64 20 74 6f 20 64 6f 20 74 68  ..%Need to do th
0700: 69 73 20 72 65 63 75 72 73 69 76 65 6c 79 0a 09  is recursively..
0710: 5b 20 23 78 6d 6c 41 74 74 72 69 62 75 74 65 7b  [ #xmlAttribute{
0720: 76 61 6c 75 65 3d 4c 6f 63 61 74 69 6f 6e 7d 20  value=Location} 
0730: 5d 20 3d 20 78 6d 65 72 6c 5f 78 70 61 74 68 3a  ] = xmerl_xpath:
0740: 73 74 72 69 6e 67 28 22 40 6e 61 6d 65 22 2c 20  string("@name", 
0750: 4e 6f 64 65 29 2c 0a 09 5b 20 23 78 6d 6c 41 74  Node),..[ #xmlAt
0760: 74 72 69 62 75 74 65 7b 76 61 6c 75 65 3d 49 44  tribute{value=ID
0770: 7d 20 5d 20 3d 20 78 6d 65 72 6c 5f 78 70 61 74  } ] = xmerl_xpat
0780: 68 3a 73 74 72 69 6e 67 28 22 40 69 64 22 2c 20  h:string("@id", 
0790: 4e 6f 64 65 29 2c 0a 09 69 6f 3a 66 6f 72 6d 61  Node),..io:forma
07a0: 74 28 4c 6f 63 61 74 69 6f 6e 2b 2b 22 2c 20 22  t(Location++", "
07b0: 2b 2b 49 44 2b 2b 22 7e 6e 22 29 2c 0a 09 70 72  ++ID++"~n"),..pr
07c0: 69 6e 74 5f 6c 6f 63 61 74 69 6f 6e 73 28 52 65  int_locations(Re
07d0: 73 74 29 2e 0a 0a 0a 67 65 74 5f 77 65 61 74 68  st)....get_weath
07e0: 65 72 28 4c 6f 63 61 74 69 6f 6e 2c 20 7b 20 44  er(Location, { D
07f0: 61 74 65 5f 66 6f 72 6d 61 74 74 65 64 2c 20 52  ate_formatted, R
0800: 65 70 20 7d 29 20 2d 3e 0a 09 69 6e 65 74 73 3a  ep }) ->..inets:
0810: 73 74 61 72 74 28 29 2c 0a 09 4b 65 79 20 3d 20  start(),..Key = 
0820: 72 65 61 64 61 70 69 6b 65 79 28 29 2c 0a 09 55  readapikey(),..U
0830: 52 4c 20 3d 20 3f 42 41 53 45 5f 55 52 4c 20 2b  RL = ?BASE_URL +
0840: 2b 20 3f 57 58 46 43 53 5f 4c 4f 43 41 54 49 4f  + ?WXFCS_LOCATIO
0850: 4e 49 44 20 2b 2b 20 4c 6f 63 61 74 69 6f 6e 20  NID ++ Location 
0860: 2b 2b 20 22 3f 6b 65 79 3d 22 20 2b 2b 20 4b 65  ++ "?key=" ++ Ke
0870: 79 20 2b 2b 20 22 26 72 65 73 3d 33 68 6f 75 72  y ++ "&res=3hour
0880: 6c 79 22 2c 0a 09 74 72 79 0a 09 09 7b 20 6f 6b  ly",..try...{ ok
0890: 2c 20 7b 5f 53 74 61 74 75 73 2c 20 5f 48 65 61  , {_Status, _Hea
08a0: 64 65 72 73 2c 20 42 6f 64 79 20 7d 7d 20 3d 20  ders, Body }} = 
08b0: 68 74 74 70 63 3a 72 65 71 75 65 73 74 28 67 65  httpc:request(ge
08c0: 74 2c 20 7b 55 52 4c 2c 20 5b 5d 7d 2c 20 5b 7b  t, {URL, []}, [{
08d0: 74 69 6d 65 6f 75 74 2c 20 74 69 6d 65 72 3a 73  timeout, timer:s
08e0: 65 63 6f 6e 64 73 28 31 30 29 7d 5d 2c 20 5b 5d  econds(10)}], []
08f0: 29 2c 0a 09 09 7b 20 58 6d 6c 2c 20 5f 52 65 73  ),...{ Xml, _Res
0900: 74 20 7d 20 3d 20 78 6d 65 72 6c 5f 73 63 61 6e  t } = xmerl_scan
0910: 3a 73 74 72 69 6e 67 28 42 6f 64 79 29 2c 0a 09  :string(Body),..
0920: 09 5b 20 5b 20 23 78 6d 6c 41 74 74 72 69 62 75  .[ [ #xmlAttribu
0930: 74 65 7b 76 61 6c 75 65 3d 44 69 72 65 63 74 69  te{value=Directi
0940: 6f 6e 7d 20 5d 2c 0a 09 09 20 20 5b 20 23 78 6d  on} ],...  [ #xm
0950: 6c 41 74 74 72 69 62 75 74 65 7b 76 61 6c 75 65  lAttribute{value
0960: 3d 53 70 65 65 64 7d 20 5d 2c 0a 09 09 20 20 5b  =Speed} ],...  [
0970: 20 23 78 6d 6c 41 74 74 72 69 62 75 74 65 7b 76   #xmlAttribute{v
0980: 61 6c 75 65 3d 47 75 73 74 7d 20 5d 2c 0a 09 09  alue=Gust} ],...
0990: 20 20 5b 20 23 78 6d 6c 41 74 74 72 69 62 75 74    [ #xmlAttribut
09a0: 65 7b 76 61 6c 75 65 3d 57 65 61 74 68 65 72 7d  e{value=Weather}
09b0: 20 5d 2c 0a 09 09 20 20 5b 20 23 78 6d 6c 41 74   ],...  [ #xmlAt
09c0: 74 72 69 62 75 74 65 7b 76 61 6c 75 65 3d 54 65  tribute{value=Te
09d0: 6d 70 65 72 61 74 75 72 65 7d 20 5d 20 5d 20 3d  mperature} ] ] =
09e0: 20 6c 69 73 74 73 3a 6d 61 70 28 0a 09 09 09 66   lists:map(....f
09f0: 75 6e 28 58 29 20 2d 3e 0a 09 09 09 09 78 6d 65  un(X) ->.....xme
0a00: 72 6c 5f 78 70 61 74 68 3a 73 74 72 69 6e 67 28  rl_xpath:string(
0a10: 22 2f 2f 50 65 72 69 6f 64 5b 40 76 61 6c 75 65  "//Period[@value
0a20: 3d 27 22 20 2b 2b 20 44 61 74 65 5f 66 6f 72 6d  ='" ++ Date_form
0a30: 61 74 74 65 64 20 2b 2b 20 22 27 5d 2f 52 65 70  atted ++ "']/Rep
0a40: 5b 2e 3d 27 22 20 2b 2b 20 52 65 70 20 2b 2b 20  [.='" ++ Rep ++ 
0a50: 22 27 5d 2f 40 22 2b 2b 58 2c 20 58 6d 6c 29 0a  "']/@"++X, Xml).
0a60: 09 09 09 65 6e 64 2c 0a 09 09 09 5b 22 44 22 2c  ...end,....["D",
0a70: 20 22 53 22 2c 20 22 47 22 2c 20 22 57 22 2c 20   "S", "G", "W", 
0a80: 22 54 22 5d 29 2c 0a 09 09 7b 44 69 72 65 63 74  "T"]),...{Direct
0a90: 69 6f 6e 2c 20 53 70 65 65 64 2c 20 47 75 73 74  ion, Speed, Gust
0aa0: 2c 20 57 65 61 74 68 65 72 2c 20 54 65 6d 70 65  , Weather, Tempe
0ab0: 72 61 74 75 72 65 7d 0a 09 63 61 74 63 68 0a 09  rature}..catch..
0ac0: 09 5f 3a 52 65 61 73 6f 6e 20 2d 3e 0a 09 09 09  ._:Reason ->....
0ad0: 69 6f 3a 66 6f 72 6d 61 74 28 22 41 50 49 20 4d  io:format("API M
0ae0: 69 67 68 74 20 62 65 20 64 6f 77 6e 7e 6e 22 29  ight be down~n")
0af0: 2c 0a 09 09 09 52 65 61 73 6f 6e 0a 09 61 66 74  ,....Reason..aft
0b00: 65 72 0a 09 09 6d 61 79 62 65 5f 71 75 69 74 28  er...maybe_quit(
0b10: 29 0a 09 65 6e 64 2e 0a 0a 0a 64 61 74 65 5f 61  )..end....date_a
0b20: 6e 64 5f 72 65 70 28 44 61 74 65 29 20 2d 3e 0a  nd_rep(Date) ->.
0b30: 09 7b 7b 5f 59 65 61 72 2c 20 5f 4d 6f 6e 74 68  .{{_Year, _Month
0b40: 2c 20 5f 44 61 79 7d 2c 20 7b 48 6f 75 72 73 2c  , _Day}, {Hours,
0b50: 20 5f 4d 69 6e 75 74 65 73 2c 20 5f 53 65 63 6f   _Minutes, _Seco
0b60: 6e 64 73 7d 7d 20 3d 20 44 61 74 65 2c 0a 09 64  nds}} = Date,..d
0b70: 61 74 65 5f 61 6e 64 5f 72 65 70 28 44 61 74 65  ate_and_rep(Date
0b80: 2c 20 48 6f 75 72 73 29 2e 0a 64 61 74 65 5f 61  , Hours)..date_a
0b90: 6e 64 5f 72 65 70 28 44 61 74 65 2c 20 48 6f 75  nd_rep(Date, Hou
0ba0: 72 73 29 20 77 68 65 6e 20 48 6f 75 72 73 20 3c  rs) when Hours <
0bb0: 20 38 20 2d 3e 0a 09 52 65 70 20 3d 20 22 33 36   8 ->..Rep = "36
0bc0: 30 22 2c 0a 09 7b 66 6f 72 6d 61 74 5f 64 61 74  0",..{format_dat
0bd0: 65 28 44 61 74 65 29 2c 20 52 65 70 7d 3b 0a 64  e(Date), Rep};.d
0be0: 61 74 65 5f 61 6e 64 5f 72 65 70 28 44 61 74 65  ate_and_rep(Date
0bf0: 2c 20 48 6f 75 72 73 29 20 77 68 65 6e 20 48 6f  , Hours) when Ho
0c00: 75 72 73 20 3e 3d 20 38 2c 20 48 6f 75 72 73 20  urs >= 8, Hours 
0c10: 3c 20 31 39 20 2d 3e 0a 09 52 65 70 20 3d 20 22  < 19 ->..Rep = "
0c20: 31 30 38 30 22 2c 0a 09 7b 66 6f 72 6d 61 74 5f  1080",..{format_
0c30: 64 61 74 65 28 44 61 74 65 29 2c 20 52 65 70 7d  date(Date), Rep}
0c40: 3b 0a 64 61 74 65 5f 61 6e 64 5f 72 65 70 28 44  ;.date_and_rep(D
0c50: 61 74 65 2c 20 48 6f 75 72 73 29 20 77 68 65 6e  ate, Hours) when
0c60: 20 48 6f 75 72 73 20 3e 3d 20 31 39 20 2d 3e 0a   Hours >= 19 ->.
0c70: 09 52 65 70 20 3d 20 22 33 36 30 22 2c 0a 09 7b  .Rep = "360",..{
0c80: 66 6f 72 6d 61 74 5f 64 61 74 65 28 66 69 6e 64  format_date(find
0c90: 5f 6e 65 78 74 5f 64 61 79 28 44 61 74 65 29 29  _next_day(Date))
0ca0: 2c 20 52 65 70 7d 2e 0a 0a 0a 66 6f 72 6d 61 74  , Rep}....format
0cb0: 5f 64 61 74 65 28 44 61 74 65 5f 74 6f 5f 66 6f  _date(Date_to_fo
0cc0: 72 6d 61 74 29 20 2d 3e 0a 09 7b 7b 59 65 61 72  rmat) ->..{{Year
0cd0: 2c 20 4d 6f 6e 74 68 2c 20 44 61 79 7d 2c 20 7b  , Month, Day}, {
0ce0: 5f 48 6f 75 72 73 2c 20 5f 4d 69 6e 75 74 65 73  _Hours, _Minutes
0cf0: 2c 20 5f 53 65 63 6f 6e 64 73 7d 7d 20 3d 20 44  , _Seconds}} = D
0d00: 61 74 65 5f 74 6f 5f 66 6f 72 6d 61 74 2c 0a 09  ate_to_format,..
0d10: 25 54 68 61 6e 6b 73 20 74 6f 3a 20 68 74 74 70  %Thanks to: http
0d20: 3a 2f 2f 73 74 61 63 6b 6f 76 65 72 66 6c 6f 77  ://stackoverflow
0d30: 2e 63 6f 6d 2f 61 2f 37 35 39 39 35 30 36 2f 32  .com/a/7599506/2
0d40: 30 38 37 39 33 0a 09 44 61 74 65 5f 61 73 5f 73  08793..Date_as_s
0d50: 74 72 69 6e 67 20 3d 20 69 6f 5f 6c 69 62 3a 66  tring = io_lib:f
0d60: 6f 72 6d 61 74 28 22 7e 34 2e 2e 30 77 2d 7e 32  ormat("~4..0w-~2
0d70: 2e 2e 30 77 2d 7e 32 2e 2e 30 77 5a 22 2c 20 5b  ..0w-~2..0wZ", [
0d80: 59 65 61 72 2c 20 4d 6f 6e 74 68 2c 20 44 61 79  Year, Month, Day
0d90: 5d 29 2c 0a 09 6c 69 73 74 73 3a 66 6c 61 74 74  ]),..lists:flatt
0da0: 65 6e 28 44 61 74 65 5f 61 73 5f 73 74 72 69 6e  en(Date_as_strin
0db0: 67 29 2e 0a 0a 0a 6e 74 68 5f 77 72 61 70 28 4e  g)....nth_wrap(N
0dc0: 2c 20 4c 69 73 74 29 20 2d 3e 0a 09 52 65 6d 20  , List) ->..Rem 
0dd0: 3d 20 4e 20 72 65 6d 20 28 6c 65 6e 67 74 68 28  = N rem (length(
0de0: 4c 69 73 74 29 29 2c 0a 09 69 66 20 52 65 6d 20  List)),..if Rem 
0df0: 3e 20 30 20 2d 3e 0a 09 09 6c 69 73 74 73 3a 6e  > 0 ->...lists:n
0e00: 74 68 28 52 65 6d 2c 20 4c 69 73 74 29 3b 0a 09  th(Rem, List);..
0e10: 52 65 6d 20 3d 3a 3d 20 30 20 2d 3e 0a 09 09 25  Rem =:= 0 ->...%
0e20: 47 65 74 20 6c 61 73 74 20 6f 66 20 6c 69 73 74  Get last of list
0e30: 0a 09 09 68 64 28 6c 69 73 74 73 3a 72 65 76 65  ...hd(lists:reve
0e40: 72 73 65 28 4c 69 73 74 29 29 0a 09 65 6e 64 2e  rse(List))..end.
0e50: 0a 0a 0a 66 69 6e 64 5f 6e 65 78 74 5f 64 61 79  ...find_next_day
0e60: 28 44 61 74 65 5f 74 6f 64 61 79 29 20 2d 3e 0a  (Date_today) ->.
0e70: 09 25 67 65 74 20 69 6e 20 73 65 63 6f 6e 64 73  .%get in seconds
0e80: 0a 09 53 65 63 6f 6e 64 73 5f 74 6f 64 61 79 20  ..Seconds_today 
0e90: 3d 20 63 61 6c 65 6e 64 61 72 3a 64 61 74 65 74  = calendar:datet
0ea0: 69 6d 65 5f 74 6f 5f 67 72 65 67 6f 72 69 61 6e  ime_to_gregorian
0eb0: 5f 73 65 63 6f 6e 64 73 28 44 61 74 65 5f 74 6f  _seconds(Date_to
0ec0: 64 61 79 29 2c 0a 09 44 61 74 65 5f 74 6f 6d 6f  day),..Date_tomo
0ed0: 72 72 6f 77 20 3d 20 63 61 6c 65 6e 64 61 72 3a  rrow = calendar:
0ee0: 67 72 65 67 6f 72 69 61 6e 5f 73 65 63 6f 6e 64  gregorian_second
0ef0: 73 5f 74 6f 5f 64 61 74 65 74 69 6d 65 28 53 65  s_to_datetime(Se
0f00: 63 6f 6e 64 73 5f 74 6f 64 61 79 2b 38 36 34 30  conds_today+8640
0f10: 30 29 2c 0a 09 44 61 74 65 5f 74 6f 6d 6f 72 72  0),..Date_tomorr
0f20: 6f 77 2e 0a 0a 0a 6d 61 79 62 65 5f 71 75 69 74  ow....maybe_quit
0f30: 28 29 20 2d 3e 0a 09 41 72 67 73 20 3d 20 69 6e  () ->..Args = in
0f40: 69 74 3a 67 65 74 5f 61 72 67 75 6d 65 6e 74 73  it:get_arguments
0f50: 28 29 2c 20 0a 09 46 6f 75 6e 64 20 3d 20 6c 69  (), ..Found = li
0f60: 73 74 73 3a 6b 65 79 66 69 6e 64 28 6e 6f 73 68  sts:keyfind(nosh
0f70: 65 6c 6c 2c 20 31 2c 20 41 72 67 73 29 2c 0a 09  ell, 1, Args),..
0f80: 69 66 20 46 6f 75 6e 64 20 3d 3a 3d 20 66 61 6c  if Found =:= fal
0f90: 73 65 20 2d 3e 0a 09 09 64 6f 6e 74 5f 71 75 69  se ->...dont_qui
0fa0: 74 3b 0a 09 74 72 75 65 20 2d 3e 0a 09 09 69 6e  t;..true ->...in
0fb0: 69 74 3a 73 74 6f 70 28 29 0a 09 65 6e 64 2e 0a  it:stop()..end..
0fc0: 0a 0a 25 46 72 6f 6d 3a 20 68 74 74 70 3a 2f 2f  ..%From: http://
0fd0: 77 77 77 2e 63 6f 64 65 63 6f 64 65 78 2e 63 6f  www.codecodex.co
0fe0: 6d 2f 77 69 6b 69 2f 69 6e 64 65 78 2e 70 68 70  m/wiki/index.php
0ff0: 3f 74 69 74 6c 65 3d 52 6f 75 6e 64 5f 61 5f 6e  ?title=Round_a_n
1000: 75 6d 62 65 72 5f 74 6f 5f 61 5f 73 70 65 63 69  umber_to_a_speci
1010: 66 69 63 5f 64 65 63 69 6d 61 6c 5f 70 6c 61 63  fic_decimal_plac
1020: 65 23 45 72 6c 61 6e 67 0a 72 6f 75 6e 64 28 4e  e#Erlang.round(N
1030: 75 6d 62 65 72 2c 20 50 72 65 63 69 73 69 6f 6e  umber, Precision
1040: 29 20 2d 3e 0a 09 50 20 3d 20 6d 61 74 68 3a 70  ) ->..P = math:p
1050: 6f 77 28 31 30 2c 20 50 72 65 63 69 73 69 6f 6e  ow(10, Precision
1060: 29 2c 0a 09 09 72 6f 75 6e 64 28 4e 75 6d 62 65  ),...round(Numbe
1070: 72 20 2a 20 50 29 20 2f 20 50 2e 0a 0a 0a 62 75  r * P) / P....bu
1080: 69 6c 64 5f 6c 69 73 74 5f 6f 66 5f 77 69 6e 64  ild_list_of_wind
1090: 5f 64 69 72 65 63 74 69 6f 6e 73 28 57 69 6e 64  _directions(Wind
10a0: 5f 64 69 72 65 63 74 69 6f 6e 29 20 2d 3e 0a 09  _direction) ->..
10b0: 25 54 68 65 72 65 20 69 73 20 6f 6e 6c 79 20 6f  %There is only o
10c0: 6e 65 20 77 69 6e 64 20 64 69 72 65 63 74 69 6f  ne wind directio
10d0: 6e 2c 20 62 75 74 20 63 61 6e 20 62 75 69 6c 64  n, but can build
10e0: 20 67 72 6f 75 70 73 20 6f 66 20 64 69 72 65 63   groups of direc
10f0: 74 69 6f 6e 73 20 74 68 61 74 20 77 69 6c 6c 20  tions that will 
1100: 63 6f 75 6e 74 20 61 73 20 68 65 61 64 2c 20 73  count as head, s
1110: 69 64 65 20 61 6e 64 20 74 61 69 6c 20 77 69 6e  ide and tail win
1120: 64 73 0a 09 43 6f 6d 70 61 73 73 20 3d 20 5b 22  ds..Compass = ["
1130: 4e 22 2c 20 22 4e 4e 45 22 2c 20 22 4e 45 22 2c  N", "NNE", "NE",
1140: 20 22 45 4e 45 22 2c 20 22 45 22 2c 20 22 45 53   "ENE", "E", "ES
1150: 45 22 2c 20 22 53 45 22 2c 20 22 53 53 45 22 2c  E", "SE", "SSE",
1160: 20 22 53 22 2c 20 22 53 53 57 22 2c 20 22 53 57   "S", "SSW", "SW
1170: 22 2c 20 22 57 53 57 22 2c 20 22 57 22 2c 20 22  ", "WSW", "W", "
1180: 57 4e 57 22 2c 20 22 4e 57 22 2c 20 22 4e 4e 57  WNW", "NW", "NNW
1190: 22 5d 2c 0a 09 25 51 75 69 63 6b 65 72 20 64 69  "],..%Quicker di
11a0: 72 74 69 65 72 28 3f 29 20 77 61 79 20 74 6f 20  rtier(?) way to 
11b0: 64 6f 20 62 65 6c 6f 77 20 77 6f 75 6c 64 20 62  do below would b
11c0: 65 3a 20 68 74 74 70 3a 2f 2f 73 74 61 63 6b 6f  e: http://stacko
11d0: 76 65 72 66 6c 6f 77 2e 63 6f 6d 2f 61 2f 36 37  verflow.com/a/67
11e0: 36 32 31 39 31 2f 32 30 38 37 39 33 0a 09 49 6e  62191/208793..In
11f0: 64 65 78 20 3d 20 6c 65 6e 67 74 68 28 6c 69 73  dex = length(lis
1200: 74 73 3a 74 61 6b 65 77 68 69 6c 65 28 66 75 6e  ts:takewhile(fun
1210: 28 58 29 20 2d 3e 20 58 20 20 3d 2f 3d 20 57 69  (X) -> X  =/= Wi
1220: 6e 64 5f 64 69 72 65 63 74 69 6f 6e 20 65 6e 64  nd_direction end
1230: 2c 20 43 6f 6d 70 61 73 73 29 29 2b 31 2c 0a 09  , Compass))+1,..
1240: 25 53 69 6e 63 65 20 68 65 61 64 69 6e 67 20 69  %Since heading i
1250: 73 20 74 6f 20 64 69 72 65 63 74 69 6f 6e 20 61  s to direction a
1260: 6e 64 20 77 69 6e 64 73 20 61 72 65 20 66 72 6f  nd winds are fro
1270: 6d 2c 20 6f 70 70 6f 73 69 74 65 20 69 73 20 2d  m, opposite is -
1280: 32 20 74 6f 20 2b 32 2c 20 6f 72 20 74 6f 20 6d  2 to +2, or to m
1290: 61 6b 65 20 69 74 20 65 61 73 69 65 72 20 74 6f  ake it easier to
12a0: 20 77 72 61 70 2c 20 2b 31 34 20 2b 31 38 0a 09   wrap, +14 +18..
12b0: 25 53 69 6e 63 65 20 68 65 61 64 69 6e 67 20 69  %Since heading i
12c0: 73 20 74 6f 20 64 69 72 65 63 74 69 6f 6e 20 61  s to direction a
12d0: 6e 64 20 77 69 6e 64 73 20 61 72 65 20 66 72 6f  nd winds are fro
12e0: 6d 2c 20 73 69 64 65 77 69 6e 64 73 20 61 72 65  m, sidewinds are
12f0: 20 2d 35 20 74 6f 20 2d 33 20 61 6e 64 20 2b 33   -5 to -3 and +3
1300: 20 74 6f 20 2b 35 2c 20 6f 72 20 74 6f 20 6d 61   to +5, or to ma
1310: 6b 65 20 69 74 20 65 61 73 69 65 72 20 74 6f 20  ke it easier to 
1320: 77 72 61 70 2c 20 2b 31 34 20 2b 31 38 0a 09 25  wrap, +14 +18..%
1330: 41 6e 64 20 73 6f 20 6f 6e 0a 09 48 65 61 64 77  And so on..Headw
1340: 69 6e 64 5f 6c 69 73 74 20 3d 20 6c 69 73 74 73  ind_list = lists
1350: 3a 73 65 71 28 31 34 2c 31 38 29 2c 0a 09 53 69  :seq(14,18),..Si
1360: 64 65 77 69 6e 64 5f 6c 69 73 74 20 3d 20 6c 69  dewind_list = li
1370: 73 74 73 3a 73 65 71 28 33 2c 35 29 2b 2b 6c 69  sts:seq(3,5)++li
1380: 73 74 73 3a 73 65 71 28 31 31 2c 31 33 29 2c 0a  sts:seq(11,13),.
1390: 09 54 61 69 6c 77 69 6e 64 5f 6c 69 73 74 20 3d  .Tailwind_list =
13a0: 20 6c 69 73 74 73 3a 73 65 71 28 36 2c 31 30 29   lists:seq(6,10)
13b0: 2c 0a 09 6c 69 73 74 73 3a 6d 61 70 28 0a 09 09  ,..lists:map(...
13c0: 66 75 6e 28 57 69 6e 64 5f 6c 69 73 74 29 20 2d  fun(Wind_list) -
13d0: 3e 0a 09 09 09 6c 69 73 74 73 3a 6d 61 70 28 0a  >....lists:map(.
13e0: 09 09 09 09 66 75 6e 28 58 29 20 2d 3e 0a 09 09  ....fun(X) ->...
13f0: 09 09 09 6e 74 68 5f 77 72 61 70 28 49 6e 64 65  ...nth_wrap(Inde
1400: 78 2b 58 2c 20 43 6f 6d 70 61 73 73 29 0a 09 09  x+X, Compass)...
1410: 09 09 65 6e 64 2c 0a 09 09 09 09 57 69 6e 64 5f  ..end,.....Wind_
1420: 6c 69 73 74 29 0a 09 09 65 6e 64 2c 0a 09 09 5b  list)...end,...[
1430: 48 65 61 64 77 69 6e 64 5f 6c 69 73 74 2c 20 53  Headwind_list, S
1440: 69 64 65 77 69 6e 64 5f 6c 69 73 74 2c 20 54 61  idewind_list, Ta
1450: 69 6c 77 69 6e 64 5f 6c 69 73 74 5d 29 2e 0a 0a  ilwind_list])...
1460: 0a 63 6f 6e 76 65 72 74 5f 6c 61 74 73 5f 6c 6f  .convert_lats_lo
1470: 6e 67 73 5f 74 6f 5f 64 69 73 74 61 6e 63 65 5f  ngs_to_distance_
1480: 68 65 61 64 69 6e 67 28 5b 5f 48 65 61 64 31 20  heading([_Head1 
1490: 7c 20 5b 20 5f 48 65 61 64 32 20 7c 20 52 65 73  | [ _Head2 | Res
14a0: 74 5d 5d 29 20 20 2d 3e 20 0a 09 25 41 6c 6c 20  t]])  -> ..%All 
14b0: 63 6f 2d 6f 72 64 73 20 61 72 65 20 64 69 66 66  co-ords are diff
14c0: 2c 20 73 6f 20 6a 75 73 74 20 69 67 6e 6f 72 65  , so just ignore
14d0: 20 66 69 72 73 74 20 74 77 6f 0a 09 63 6f 6e 76   first two..conv
14e0: 65 72 74 5f 6c 61 74 73 5f 6c 6f 6e 67 73 5f 74  ert_lats_longs_t
14f0: 6f 5f 64 69 73 74 61 6e 63 65 5f 68 65 61 64 69  o_distance_headi
1500: 6e 67 5f 28 52 65 73 74 2c 20 5b 5d 29 2e 0a 63  ng_(Rest, [])..c
1510: 6f 6e 76 65 72 74 5f 6c 61 74 73 5f 6c 6f 6e 67  onvert_lats_long
1520: 73 5f 74 6f 5f 64 69 73 74 61 6e 63 65 5f 68 65  s_to_distance_he
1530: 61 64 69 6e 67 5f 28 5b 4c 61 74 20 7c 20 5b 4c  ading_([Lat | [L
1540: 6f 6e 20 7c 20 52 65 73 74 5d 5d 2c 20 44 69 73  on | Rest]], Dis
1550: 74 61 6e 63 65 5f 68 65 61 64 69 6e 67 73 5f 6c  tance_headings_l
1560: 69 73 74 29 20 2d 3e 0a 09 25 57 61 6e 74 20 74  ist) ->..%Want t
1570: 6f 20 6d 61 70 20 74 68 72 6f 75 67 68 20 74 68  o map through th
1580: 65 20 6c 69 73 74 20 63 6f 6e 76 65 72 74 20 63  e list convert c
1590: 6f 2d 6f 72 64 73 20 74 6f 20 64 69 73 74 61 6e  o-ords to distan
15a0: 63 65 20 61 6e 64 20 68 65 61 64 69 6e 67 0a 09  ce and heading..
15b0: 44 69 73 74 61 6e 63 65 20 3d 20 6d 61 74 68 3a  Distance = math:
15c0: 73 71 72 74 28 6d 61 74 68 3a 70 6f 77 28 4c 61  sqrt(math:pow(La
15d0: 74 2c 32 29 20 2b 20 6d 61 74 68 3a 70 6f 77 28  t,2) + math:pow(
15e0: 4c 6f 6e 2c 32 29 29 2c 0a 09 48 65 61 64 69 6e  Lon,2)),..Headin
15f0: 67 5f 73 69 67 6e 65 64 20 3d 20 6d 61 74 68 3a  g_signed = math:
1600: 61 74 61 6e 32 28 4c 6f 6e 2c 20 4c 61 74 29 2c  atan2(Lon, Lat),
1610: 0a 09 25 4e 65 65 64 20 74 6f 20 63 6f 6e 76 65  ..%Need to conve
1620: 72 74 20 68 65 61 64 69 6e 67 20 69 6e 74 6f 20  rt heading into 
1630: 61 20 32 cf 80 20 76 61 6c 75 65 0a 09 48 65 61  a 2π value..Hea
1640: 64 69 6e 67 20 3d 20 69 66 20 48 65 61 64 69 6e  ding = if Headin
1650: 67 5f 73 69 67 6e 65 64 20 3c 20 30 20 2d 3e 0a  g_signed < 0 ->.
1660: 09 09 09 09 48 65 61 64 69 6e 67 5f 73 69 67 6e  ....Heading_sign
1670: 65 64 20 2b 20 32 2a 6d 61 74 68 3a 70 69 28 29  ed + 2*math:pi()
1680: 3b 0a 09 09 09 74 72 75 65 20 2d 3e 0a 09 09 09  ;....true ->....
1690: 09 48 65 61 64 69 6e 67 5f 73 69 67 6e 65 64 0a  .Heading_signed.
16a0: 09 09 09 65 6e 64 2c 0a 09 63 6f 6e 76 65 72 74  ...end,..convert
16b0: 5f 6c 61 74 73 5f 6c 6f 6e 67 73 5f 74 6f 5f 64  _lats_longs_to_d
16c0: 69 73 74 61 6e 63 65 5f 68 65 61 64 69 6e 67 5f  istance_heading_
16d0: 28 52 65 73 74 2c 20 5b 7b 44 69 73 74 61 6e 63  (Rest, [{Distanc
16e0: 65 2c 20 48 65 61 64 69 6e 67 7d 5d 2b 2b 44 69  e, Heading}]++Di
16f0: 73 74 61 6e 63 65 5f 68 65 61 64 69 6e 67 73 5f  stance_headings_
1700: 6c 69 73 74 29 3b 0a 63 6f 6e 76 65 72 74 5f 6c  list);.convert_l
1710: 61 74 73 5f 6c 6f 6e 67 73 5f 74 6f 5f 64 69 73  ats_longs_to_dis
1720: 74 61 6e 63 65 5f 68 65 61 64 69 6e 67 5f 28 5b  tance_heading_([
1730: 5d 2c 20 44 69 73 74 61 6e 63 65 5f 68 65 61 64  ], Distance_head
1740: 69 6e 67 73 5f 6c 69 73 74 29 20 2d 3e 0a 09 6c  ings_list) ->..l
1750: 69 73 74 73 3a 72 65 76 65 72 73 65 28 44 69 73  ists:reverse(Dis
1760: 74 61 6e 63 65 5f 68 65 61 64 69 6e 67 73 5f 6c  tance_headings_l
1770: 69 73 74 29 2e 0a 0a 0a 6a 6f 75 72 6e 65 79 28  ist)....journey(
1780: 44 69 73 74 61 6e 63 65 5f 68 65 61 64 69 6e 67  Distance_heading
1790: 73 5f 6c 69 73 74 29 20 2d 3e 0a 09 6c 69 73 74  s_list) ->..list
17a0: 73 3a 6d 61 70 28 0a 09 09 66 75 6e 28 7b 44 69  s:map(...fun({Di
17b0: 73 74 61 6e 63 65 2c 20 48 65 61 64 69 6e 67 7d  stance, Heading}
17c0: 29 20 2d 3e 0a 09 09 09 43 6f 6d 70 61 73 73 5f  ) ->....Compass_
17d0: 64 69 72 65 63 74 69 6f 6e 20 3d 20 67 65 74 5f  direction = get_
17e0: 63 6f 6d 70 61 73 73 5f 64 69 72 65 63 74 69 6f  compass_directio
17f0: 6e 5f 66 6f 72 28 48 65 61 64 69 6e 67 29 2c 0a  n_for(Heading),.
1800: 09 09 09 7b 44 69 73 74 61 6e 63 65 2c 20 43 6f  ...{Distance, Co
1810: 6d 70 61 73 73 5f 64 69 72 65 63 74 69 6f 6e 7d  mpass_direction}
1820: 0a 09 09 65 6e 64 2c 0a 09 09 44 69 73 74 61 6e  ...end,...Distan
1830: 63 65 5f 68 65 61 64 69 6e 67 73 5f 6c 69 73 74  ce_headings_list
1840: 29 2e 0a 0a 0a 72 65 76 65 72 73 65 5f 6a 6f 75  )....reverse_jou
1850: 72 6e 65 79 28 44 69 73 74 61 6e 63 65 5f 68 65  rney(Distance_he
1860: 61 64 69 6e 67 73 5f 6c 69 73 74 29 20 2d 3e 0a  adings_list) ->.
1870: 09 25 44 6f 6e 27 74 20 61 63 74 75 61 6c 6c 79  .%Don't actually
1880: 20 6e 65 65 64 20 61 20 63 6f 72 72 65 63 74 6c   need a correctl
1890: 79 20 6f 72 64 65 72 65 64 20 72 65 76 65 72 73  y ordered revers
18a0: 65 20 72 6f 75 74 65 2c 20 61 73 20 6c 6f 6e 67  e route, as long
18b0: 20 61 73 20 77 65 20 68 61 76 65 20 64 69 72 65   as we have dire
18c0: 63 74 69 6f 6e 73 20 61 6e 64 20 64 69 73 74 61  ctions and dista
18d0: 6e 63 65 73 2e 0a 09 6c 69 73 74 73 3a 6d 61 70  nces...lists:map
18e0: 28 0a 09 09 66 75 6e 28 7b 44 69 73 74 61 6e 63  (...fun({Distanc
18f0: 65 2c 20 48 65 61 64 69 6e 67 7d 29 20 2d 3e 0a  e, Heading}) ->.
1900: 09 09 09 25 42 65 63 61 75 73 65 20 63 61 6e 27  ...%Because can'
1910: 74 20 68 61 76 65 20 66 75 6e 63 74 69 6f 6e 73  t have functions
1920: 20 69 6e 20 67 75 61 72 64 73 0a 09 09 09 50 69   in guards....Pi
1930: 20 3d 20 6d 61 74 68 3a 70 69 28 29 2c 0a 09 09   = math:pi(),...
1940: 09 52 65 76 65 72 73 65 5f 68 65 61 64 69 6e 67  .Reverse_heading
1950: 20 3d 20 69 66 20 48 65 61 64 69 6e 67 20 3c 20   = if Heading < 
1960: 50 69 20 2d 3e 0a 09 09 09 09 48 65 61 64 69 6e  Pi ->.....Headin
1970: 67 20 2b 20 50 69 3b 0a 09 09 09 48 65 61 64 69  g + Pi;....Headi
1980: 6e 67 20 3e 3d 20 50 69 20 2d 3e 0a 09 09 09 09  ng >= Pi ->.....
1990: 48 65 61 64 69 6e 67 20 2d 20 50 69 0a 09 09 09  Heading - Pi....
19a0: 65 6e 64 2c 0a 09 09 09 43 6f 6d 70 61 73 73 5f  end,....Compass_
19b0: 64 69 72 65 63 74 69 6f 6e 20 3d 20 67 65 74 5f  direction = get_
19c0: 63 6f 6d 70 61 73 73 5f 64 69 72 65 63 74 69 6f  compass_directio
19d0: 6e 5f 66 6f 72 28 52 65 76 65 72 73 65 5f 68 65  n_for(Reverse_he
19e0: 61 64 69 6e 67 29 2c 0a 09 09 09 7b 44 69 73 74  ading),....{Dist
19f0: 61 6e 63 65 2c 20 43 6f 6d 70 61 73 73 5f 64 69  ance, Compass_di
1a00: 72 65 63 74 69 6f 6e 7d 0a 09 09 65 6e 64 2c 0a  rection}...end,.
1a10: 09 09 44 69 73 74 61 6e 63 65 5f 68 65 61 64 69  ..Distance_headi
1a20: 6e 67 73 5f 6c 69 73 74 29 2e 0a 0a 0a 67 65 74  ngs_list)....get
1a30: 5f 63 6f 6d 70 61 73 73 5f 64 69 72 65 63 74 69  _compass_directi
1a40: 6f 6e 5f 66 6f 72 28 48 65 61 64 69 6e 67 29 20  on_for(Heading) 
1a50: 2d 3e 0a 09 25 49 6e 20 61 20 77 61 79 20 74 68  ->..%In a way th
1a60: 69 73 20 69 73 20 61 20 77 61 73 74 65 20 6f 66  is is a waste of
1a70: 20 74 69 6d 65 20 61 73 20 63 6f 75 6c 64 20 6a   time as could j
1a80: 75 73 74 20 64 6f 20 68 65 61 64 77 69 6e 64 2c  ust do headwind,
1a90: 20 65 74 63 20 62 61 73 65 64 20 6f 6e 20 61 6e   etc based on an
1aa0: 67 6c 65 73 2c 20 62 75 74 20 73 69 6e 63 65 20  gles, but since 
1ab0: 61 6c 72 65 61 64 79 20 68 61 76 65 20 73 6f 6d  already have som
1ac0: 65 20 63 6f 64 65 2c 20 77 68 79 20 6e 6f 74 3f  e code, why not?
1ad0: 0a 09 53 65 67 6d 65 6e 74 20 3d 20 32 2a 6d 61  ..Segment = 2*ma
1ae0: 74 68 3a 70 69 28 29 2f 31 36 2c 0a 09 53 65 67  th:pi()/16,..Seg
1af0: 6d 65 6e 74 73 20 3d 20 65 72 6c 61 6e 67 3a 72  ments = erlang:r
1b00: 6f 75 6e 64 28 48 65 61 64 69 6e 67 2f 53 65 67  ound(Heading/Seg
1b10: 6d 65 6e 74 29 2b 31 2c 0a 09 43 6f 6d 70 61 73  ment)+1,..Compas
1b20: 73 20 3d 20 5b 22 4e 22 2c 20 22 4e 4e 45 22 2c  s = ["N", "NNE",
1b30: 20 22 4e 45 22 2c 20 22 45 4e 45 22 2c 20 22 45   "NE", "ENE", "E
1b40: 22 2c 20 22 45 53 45 22 2c 20 22 53 45 22 2c 20  ", "ESE", "SE", 
1b50: 22 53 53 45 22 2c 20 22 53 22 2c 20 22 53 53 57  "SSE", "S", "SSW
1b60: 22 2c 20 22 53 57 22 2c 20 22 57 53 57 22 2c 20  ", "SW", "WSW", 
1b70: 22 57 22 2c 20 22 57 4e 57 22 2c 20 22 4e 57 22  "W", "WNW", "NW"
1b80: 2c 20 22 4e 4e 57 22 5d 2c 0a 09 25 48 61 6e 64  , "NNW"],..%Hand
1b90: 6c 65 20 74 68 65 20 63 61 73 65 20 6f 66 20 53  le the case of S
1ba0: 65 67 6d 65 6e 74 73 20 3d 20 31 36 2e 20 4e 65  egments = 16. Ne
1bb0: 65 64 20 74 6f 20 77 72 61 70 20 61 72 6f 75 6e  ed to wrap aroun
1bc0: 64 2e 0a 09 6e 74 68 5f 77 72 61 70 28 53 65 67  d...nth_wrap(Seg
1bd0: 6d 65 6e 74 73 2c 20 43 6f 6d 70 61 73 73 29 2e  ments, Compass).
1be0: 0a 0a 0a 68 65 61 64 5f 73 69 64 65 5f 6f 72 5f  ...head_side_or_
1bf0: 74 61 69 6c 5f 77 69 6e 64 28 44 69 72 65 63 74  tail_wind(Direct
1c00: 69 6f 6e 2c 20 5b 48 65 61 64 77 69 6e 64 73 2c  ion, [Headwinds,
1c10: 20 53 69 64 65 77 69 6e 64 73 2c 20 54 61 69 6c   Sidewinds, Tail
1c20: 77 69 6e 64 73 5d 29 20 2d 3e 0a 09 5b 48 65 61  winds]) ->..[Hea
1c30: 64 77 69 6e 64 2c 20 53 69 64 65 77 69 6e 64 2c  dwind, Sidewind,
1c40: 20 54 61 69 6c 77 69 6e 64 5d 20 3d 20 6c 69 73   Tailwind] = lis
1c50: 74 73 3a 6d 61 70 28 0a 09 09 66 75 6e 28 57 69  ts:map(...fun(Wi
1c60: 6e 64 73 29 20 2d 3e 0a 09 09 09 6c 69 73 74 73  nds) ->....lists
1c70: 3a 6d 65 6d 62 65 72 28 44 69 72 65 63 74 69 6f  :member(Directio
1c80: 6e 2c 20 57 69 6e 64 73 29 0a 09 09 65 6e 64 2c  n, Winds)...end,
1c90: 0a 09 09 5b 48 65 61 64 77 69 6e 64 73 2c 20 53  ...[Headwinds, S
1ca0: 69 64 65 77 69 6e 64 73 2c 20 54 61 69 6c 77 69  idewinds, Tailwi
1cb0: 6e 64 73 5d 29 2c 0a 09 69 66 20 48 65 61 64 77  nds]),..if Headw
1cc0: 69 6e 64 20 2d 3e 0a 09 09 68 65 61 64 77 69 6e  ind ->...headwin
1cd0: 64 3b 0a 09 53 69 64 65 77 69 6e 64 20 2d 3e 0a  d;..Sidewind ->.
1ce0: 09 09 73 69 64 65 77 69 6e 64 3b 0a 09 54 61 69  ..sidewind;..Tai
1cf0: 6c 77 69 6e 64 20 2d 3e 0a 09 09 74 61 69 6c 77  lwind ->...tailw
1d00: 69 6e 64 0a 09 65 6e 64 2e 0a 25 53 6f 6d 65 74  ind..end..%Somet
1d10: 68 69 6e 67 20 6c 69 6b 65 20 74 68 61 74 3f 0a  hing like that?.
1d20: 09 0a 0a 25 46 69 72 73 74 20 74 77 6f 20 66 6f  ...%First two fo
1d30: 72 20 63 6f 6d 6d 61 6e 64 20 6c 69 6e 65 20 75  r command line u
1d40: 73 61 67 65 0a 68 65 61 64 73 69 6c 6f 73 65 28  sage.headsilose(
1d50: 5b 4c 6f 63 61 74 69 6f 6e 5d 29 20 2d 3e 0a 09  [Location]) ->..
1d60: 68 65 61 64 73 69 6c 6f 73 65 5f 28 4c 6f 63 61  headsilose_(Loca
1d70: 74 69 6f 6e 29 3b 0a 68 65 61 64 73 69 6c 6f 73  tion);.headsilos
1d80: 65 28 5b 4c 6f 63 61 74 69 6f 6e 2c 20 52 6f 75  e([Location, Rou
1d90: 74 65 5f 63 68 6f 69 63 65 5d 29 20 2d 3e 0a 09  te_choice]) ->..
1da0: 68 65 61 64 73 69 6c 6f 73 65 5f 28 4c 6f 63 61  headsilose_(Loca
1db0: 74 69 6f 6e 2c 20 52 6f 75 74 65 5f 63 68 6f 69  tion, Route_choi
1dc0: 63 65 29 2e 0a 68 65 61 64 73 69 6c 6f 73 65 5f  ce)..headsilose_
1dd0: 28 4c 6f 63 61 74 69 6f 6e 29 20 2d 3e 0a 09 25  (Location) ->..%
1de0: 49 66 20 72 6f 75 74 65 20 63 68 6f 69 63 65 20  If route choice 
1df0: 6e 6f 74 20 73 70 65 63 69 66 69 65 64 20 64 65  not specified de
1e00: 66 61 75 6c 74 20 74 6f 20 64 65 66 61 75 6c 74  fault to default
1e10: 21 0a 09 25 54 68 65 20 6f 74 68 65 72 20 63 68  !..%The other ch
1e20: 6f 69 63 65 20 69 73 20 22 61 6c 74 65 72 6e 61  oice is "alterna
1e30: 74 69 76 65 5f 67 65 6f 6d 65 74 72 69 65 73 22  tive_geometries"
1e40: 2c 20 66 6f 72 20 6e 6f 77 20 49 20 74 68 69 6e  , for now I thin
1e50: 6b 20 74 68 65 72 65 20 69 73 20 6f 6e 6c 79 20  k there is only 
1e60: 65 76 65 72 20 6f 6e 65 20 61 6c 74 65 72 6e 61  ever one alterna
1e70: 74 69 76 65 20 73 6f 20 70 69 63 6b 20 74 68 69  tive so pick thi
1e80: 73 20 66 69 72 73 74 2e 0a 09 68 65 61 64 73 69  s first...headsi
1e90: 6c 6f 73 65 5f 28 4c 6f 63 61 74 69 6f 6e 2c 20  lose_(Location, 
1ea0: 22 72 6f 75 74 65 5f 67 65 6f 6d 65 74 72 79 22  "route_geometry"
1eb0: 29 2e 0a 68 65 61 64 73 69 6c 6f 73 65 5f 28 4c  )..headsilose_(L
1ec0: 6f 63 61 74 69 6f 6e 2c 20 52 6f 75 74 65 5f 63  ocation, Route_c
1ed0: 68 6f 69 63 65 29 20 2d 3e 0a 09 44 61 74 65 5f  hoice) ->..Date_
1ee0: 74 6f 64 61 79 20 3d 20 65 72 6c 61 6e 67 3a 6c  today = erlang:l
1ef0: 6f 63 61 6c 74 69 6d 65 28 29 2c 0a 09 7b 20 44  ocaltime(),..{ D
1f00: 61 74 65 5f 66 6f 72 6d 61 74 74 65 64 2c 20 52  ate_formatted, R
1f10: 65 70 20 7d 20 3d 20 64 61 74 65 5f 61 6e 64 5f  ep } = date_and_
1f20: 72 65 70 28 44 61 74 65 5f 74 6f 64 61 79 29 2c  rep(Date_today),
1f30: 0a 09 7b 44 69 72 65 63 74 69 6f 6e 2c 20 53 70  ..{Direction, Sp
1f40: 65 65 64 2c 20 47 75 73 74 2c 20 57 65 61 74 68  eed, Gust, Weath
1f50: 65 72 2c 20 54 65 6d 70 65 72 61 74 75 72 65 7d  er, Temperature}
1f60: 20 3d 20 67 65 74 5f 77 65 61 74 68 65 72 28 4c   = get_weather(L
1f70: 6f 63 61 74 69 6f 6e 2c 20 20 7b 20 44 61 74 65  ocation,  { Date
1f80: 5f 66 6f 72 6d 61 74 74 65 64 2c 20 52 65 70 20  _formatted, Rep 
1f90: 7d 29 2c 0a 09 57 65 61 74 68 65 72 5f 74 79 70  }),..Weather_typ
1fa0: 65 20 3d 20 77 65 61 74 68 65 72 5f 74 79 70 65  e = weather_type
1fb0: 73 3a 77 65 61 74 68 65 72 5f 74 79 70 65 28 65  s:weather_type(e
1fc0: 72 6c 61 6e 67 3a 6c 69 73 74 5f 74 6f 5f 69 6e  rlang:list_to_in
1fd0: 74 65 67 65 72 28 57 65 61 74 68 65 72 29 29 2c  teger(Weather)),
1fe0: 0a 09 5b 48 65 61 64 77 69 6e 64 73 2c 20 53 69  ..[Headwinds, Si
1ff0: 64 65 77 69 6e 64 73 2c 20 54 61 69 6c 77 69 6e  dewinds, Tailwin
2000: 64 73 5d 20 3d 20 62 75 69 6c 64 5f 6c 69 73 74  ds] = build_list
2010: 5f 6f 66 5f 77 69 6e 64 5f 64 69 72 65 63 74 69  _of_wind_directi
2020: 6f 6e 73 28 44 69 72 65 63 74 69 6f 6e 29 2c 0a  ons(Direction),.
2030: 09 7b 5f 43 68 65 63 6b 73 75 6d 2c 20 50 6f 6c  .{_Checksum, Pol
2040: 79 6c 69 6e 65 7d 20 3d 20 6f 73 72 6d 3a 72 65  yline} = osrm:re
2050: 61 64 5f 72 6f 75 74 65 28 52 6f 75 74 65 5f 63  ad_route(Route_c
2060: 68 6f 69 63 65 29 2c 0a 09 50 6f 6c 79 6c 69 6e  hoice),..Polylin
2070: 65 5f 64 65 63 6f 64 65 64 20 3d 20 70 6f 6c 79  e_decoded = poly
2080: 6c 69 6e 65 3a 64 65 63 6f 64 65 28 50 6f 6c 79  line:decode(Poly
2090: 6c 69 6e 65 29 2c 0a 09 44 69 73 74 61 6e 63 65  line),..Distance
20a0: 73 5f 61 6e 64 5f 68 65 61 64 69 6e 67 73 5f 6c  s_and_headings_l
20b0: 69 73 74 20 3d 20 63 6f 6e 76 65 72 74 5f 6c 61  ist = convert_la
20c0: 74 73 5f 6c 6f 6e 67 73 5f 74 6f 5f 64 69 73 74  ts_longs_to_dist
20d0: 61 6e 63 65 5f 68 65 61 64 69 6e 67 28 50 6f 6c  ance_heading(Pol
20e0: 79 6c 69 6e 65 5f 64 65 63 6f 64 65 64 29 2c 0a  yline_decoded),.
20f0: 09 25 41 20 62 65 74 74 65 72 20 72 65 70 72 65  .%A better repre
2100: 73 65 6e 74 61 74 69 6f 6e 20 74 68 61 6e 20 33  sentation than 3
2110: 36 30 20 6f 72 20 31 30 38 30 20 77 6f 75 6c 64  60 or 1080 would
2120: 20 62 65 20 62 65 74 74 65 72 20 6e 6f 77 20 74   be better now t
2130: 68 69 73 20 69 73 20 75 73 65 64 20 68 65 72 65  his is used here
2140: 20 61 73 20 77 65 6c 6c 2e 0a 09 4a 6f 75 72 6e   as well...Journ
2150: 65 79 20 3d 20 69 66 20 52 65 70 20 3d 3a 3d 20  ey = if Rep =:= 
2160: 22 33 36 30 22 20 2d 3e 0a 09 09 6a 6f 75 72 6e  "360" ->...journ
2170: 65 79 28 44 69 73 74 61 6e 63 65 73 5f 61 6e 64  ey(Distances_and
2180: 5f 68 65 61 64 69 6e 67 73 5f 6c 69 73 74 29 3b  _headings_list);
2190: 0a 09 52 65 70 20 3d 3a 3d 20 22 31 30 38 30 22  ..Rep =:= "1080"
21a0: 20 2d 3e 0a 09 09 72 65 76 65 72 73 65 5f 6a 6f   ->...reverse_jo
21b0: 75 72 6e 65 79 28 44 69 73 74 61 6e 63 65 73 5f  urney(Distances_
21c0: 61 6e 64 5f 68 65 61 64 69 6e 67 73 5f 6c 69 73  and_headings_lis
21d0: 74 29 0a 09 65 6e 64 2c 0a 09 25 49 66 20 6e 6f  t)..end,..%If no
21e0: 77 20 68 61 76 65 20 61 20 73 65 74 20 6f 66 20  w have a set of 
21f0: 63 6f 2d 6f 72 64 73 20 6e 65 65 64 20 74 6f 20  co-ords need to 
2200: 66 69 67 75 72 65 20 6f 75 74 20 64 69 73 74 61  figure out dista
2210: 6e 63 65 73 20 61 6e 64 20 64 69 72 65 63 74 69  nces and directi
2220: 6f 6e 73 0a 09 44 69 73 74 61 6e 63 65 73 5f 61  ons..Distances_a
2230: 6e 64 5f 77 69 6e 64 5f 74 79 70 65 5f 6c 69 73  nd_wind_type_lis
2240: 74 20 3d 20 6c 69 73 74 73 3a 6d 61 70 28 0a 09  t = lists:map(..
2250: 09 66 75 6e 28 7b 44 69 73 74 61 6e 63 65 2c 20  .fun({Distance, 
2260: 43 6f 6d 70 61 73 73 7d 29 20 2d 3e 0a 09 09 09  Compass}) ->....
2270: 57 69 6e 64 5f 74 79 70 65 20 3d 20 68 65 61 64  Wind_type = head
2280: 5f 73 69 64 65 5f 6f 72 5f 74 61 69 6c 5f 77 69  _side_or_tail_wi
2290: 6e 64 28 43 6f 6d 70 61 73 73 2c 20 5b 48 65 61  nd(Compass, [Hea
22a0: 64 77 69 6e 64 73 2c 20 53 69 64 65 77 69 6e 64  dwinds, Sidewind
22b0: 73 2c 20 54 61 69 6c 77 69 6e 64 73 5d 29 2c 0a  s, Tailwinds]),.
22c0: 09 09 09 7b 44 69 73 74 61 6e 63 65 2c 20 57 69  ...{Distance, Wi
22d0: 6e 64 5f 74 79 70 65 7d 0a 09 09 65 6e 64 2c 0a  nd_type}...end,.
22e0: 09 09 4a 6f 75 72 6e 65 79 29 2c 0a 09 5b 48 65  ..Journey),..[He
22f0: 61 64 77 69 6e 64 5f 64 69 73 74 61 6e 63 65 73  adwind_distances
2300: 2c 20 53 69 64 65 77 69 6e 64 5f 64 69 73 74 61  , Sidewind_dista
2310: 6e 63 65 73 2c 20 54 61 69 6c 77 69 6e 64 5f 64  nces, Tailwind_d
2320: 69 73 74 61 6e 63 65 73 5d 20 3d 20 6c 69 73 74  istances] = list
2330: 73 3a 6d 61 70 28 0a 09 09 66 75 6e 28 57 69 6e  s:map(...fun(Win
2340: 64 5f 74 79 70 65 5f 66 69 6c 74 65 72 29 20 2d  d_type_filter) -
2350: 3e 0a 09 09 09 6c 69 73 74 73 3a 66 69 6c 74 65  >....lists:filte
2360: 72 28 0a 09 09 09 09 66 75 6e 28 7b 5f 44 69 73  r(.....fun({_Dis
2370: 74 61 6e 63 65 2c 20 57 69 6e 64 5f 74 79 70 65  tance, Wind_type
2380: 7d 29 20 2d 3e 0a 09 09 09 09 09 57 69 6e 64 5f  }) ->......Wind_
2390: 74 79 70 65 20 3d 3d 20 57 69 6e 64 5f 74 79 70  type == Wind_typ
23a0: 65 5f 66 69 6c 74 65 72 0a 09 09 09 09 65 6e 64  e_filter.....end
23b0: 2c 0a 09 09 09 09 44 69 73 74 61 6e 63 65 73 5f  ,.....Distances_
23c0: 61 6e 64 5f 77 69 6e 64 5f 74 79 70 65 5f 6c 69  and_wind_type_li
23d0: 73 74 29 0a 09 09 65 6e 64 2c 0a 09 09 5b 68 65  st)...end,...[he
23e0: 61 64 77 69 6e 64 2c 20 73 69 64 65 77 69 6e 64  adwind, sidewind
23f0: 2c 20 74 61 69 6c 77 69 6e 64 5d 29 2c 0a 09 5b  , tailwind]),..[
2400: 53 75 6d 5f 6f 66 5f 68 65 61 64 77 69 6e 64 5f  Sum_of_headwind_
2410: 64 69 73 74 61 6e 63 65 73 2c 20 53 75 6d 5f 6f  distances, Sum_o
2420: 66 5f 73 69 64 65 77 69 6e 64 5f 64 69 73 74 61  f_sidewind_dista
2430: 6e 63 65 73 2c 20 53 75 6d 5f 6f 66 5f 74 61 69  nces, Sum_of_tai
2440: 6c 77 69 6e 64 5f 64 69 73 74 61 6e 63 65 73 5d  lwind_distances]
2450: 20 3d 20 6c 69 73 74 73 3a 6d 61 70 28 0a 09 09   = lists:map(...
2460: 66 75 6e 28 57 69 6e 64 5f 74 79 70 65 29 20 2d  fun(Wind_type) -
2470: 3e 0a 09 09 09 6c 69 73 74 73 3a 66 6f 6c 64 6c  >....lists:foldl
2480: 28 0a 09 09 09 09 66 75 6e 28 7b 44 69 73 74 61  (.....fun({Dista
2490: 6e 63 65 2c 20 5f 57 69 6e 64 7d 2c 20 53 75 6d  nce, _Wind}, Sum
24a0: 29 20 2d 3e 0a 09 09 09 09 09 44 69 73 74 61 6e  ) ->......Distan
24b0: 63 65 20 2b 20 53 75 6d 0a 09 09 09 09 65 6e 64  ce + Sum.....end
24c0: 2c 0a 09 09 09 09 30 2c 0a 09 09 09 09 57 69 6e  ,.....0,.....Win
24d0: 64 5f 74 79 70 65 29 0a 09 09 65 6e 64 2c 0a 09  d_type)...end,..
24e0: 09 5b 48 65 61 64 77 69 6e 64 5f 64 69 73 74 61  .[Headwind_dista
24f0: 6e 63 65 73 2c 20 53 69 64 65 77 69 6e 64 5f 64  nces, Sidewind_d
2500: 69 73 74 61 6e 63 65 73 2c 20 54 61 69 6c 77 69  istances, Tailwi
2510: 6e 64 5f 64 69 73 74 61 6e 63 65 73 5d 29 2c 0a  nd_distances]),.
2520: 09 54 6f 74 61 6c 5f 64 69 73 74 61 6e 63 65 20  .Total_distance 
2530: 3d 20 53 75 6d 5f 6f 66 5f 68 65 61 64 77 69 6e  = Sum_of_headwin
2540: 64 5f 64 69 73 74 61 6e 63 65 73 20 2b 20 53 75  d_distances + Su
2550: 6d 5f 6f 66 5f 73 69 64 65 77 69 6e 64 5f 64 69  m_of_sidewind_di
2560: 73 74 61 6e 63 65 73 20 2b 20 53 75 6d 5f 6f 66  stances + Sum_of
2570: 5f 74 61 69 6c 77 69 6e 64 5f 64 69 73 74 61 6e  _tailwind_distan
2580: 63 65 73 2c 0a 09 25 44 65 74 65 72 6d 69 6e 65  ces,..%Determine
2590: 20 77 68 69 63 68 20 69 73 20 77 6f 72 73 65 0a   which is worse.
25a0: 09 69 66 20 28 53 75 6d 5f 6f 66 5f 68 65 61 64  .if (Sum_of_head
25b0: 77 69 6e 64 5f 64 69 73 74 61 6e 63 65 73 20 3e  wind_distances >
25c0: 20 53 75 6d 5f 6f 66 5f 73 69 64 65 77 69 6e 64   Sum_of_sidewind
25d0: 5f 64 69 73 74 61 6e 63 65 73 29 20 61 6e 64 20  _distances) and 
25e0: 28 53 75 6d 5f 6f 66 5f 68 65 61 64 77 69 6e 64  (Sum_of_headwind
25f0: 5f 64 69 73 74 61 6e 63 65 73 20 3e 20 53 75 6d  _distances > Sum
2600: 5f 6f 66 5f 74 61 69 6c 77 69 6e 64 5f 64 69 73  _of_tailwind_dis
2610: 74 61 6e 63 65 73 29 20 2d 3e 0a 09 09 69 6f 3a  tances) ->...io:
2620: 66 6f 72 6d 61 74 28 22 48 65 61 64 73 20 79 6f  format("Heads yo
2630: 75 20 6c 6f 73 65 21 7e 6e 22 29 3b 0a 09 28 53  u lose!~n");..(S
2640: 75 6d 5f 6f 66 5f 74 61 69 6c 77 69 6e 64 5f 64  um_of_tailwind_d
2650: 69 73 74 61 6e 63 65 73 20 3e 20 53 75 6d 5f 6f  istances > Sum_o
2660: 66 5f 73 69 64 65 77 69 6e 64 5f 64 69 73 74 61  f_sidewind_dista
2670: 6e 63 65 73 29 20 61 6e 64 20 28 53 75 6d 5f 6f  nces) and (Sum_o
2680: 66 5f 74 61 69 6c 77 69 6e 64 5f 64 69 73 74 61  f_tailwind_dista
2690: 6e 63 65 73 20 3e 20 53 75 6d 5f 6f 66 5f 68 65  nces > Sum_of_he
26a0: 61 64 77 69 6e 64 5f 64 69 73 74 61 6e 63 65 73  adwind_distances
26b0: 29 20 2d 3e 0a 09 09 69 6f 3a 66 6f 72 6d 61 74  ) ->...io:format
26c0: 28 22 54 61 69 6c 73 20 79 6f 75 20 77 69 6e 21  ("Tails you win!
26d0: 7e 6e 22 29 3b 0a 09 28 53 75 6d 5f 6f 66 5f 73  ~n");..(Sum_of_s
26e0: 69 64 65 77 69 6e 64 5f 64 69 73 74 61 6e 63 65  idewind_distance
26f0: 73 20 3e 3d 20 53 75 6d 5f 6f 66 5f 68 65 61 64  s >= Sum_of_head
2700: 77 69 6e 64 5f 64 69 73 74 61 6e 63 65 73 29 20  wind_distances) 
2710: 61 6e 64 20 28 53 75 6d 5f 6f 66 5f 73 69 64 65  and (Sum_of_side
2720: 77 69 6e 64 5f 64 69 73 74 61 6e 63 65 73 20 3e  wind_distances >
2730: 3d 20 53 75 6d 5f 6f 66 5f 74 61 69 6c 77 69 6e  = Sum_of_tailwin
2740: 64 5f 64 69 73 74 61 6e 63 65 73 29 20 2d 3e 0a  d_distances) ->.
2750: 09 09 69 6f 3a 66 6f 72 6d 61 74 28 22 49 74 27  ..io:format("It'
2760: 73 20 61 20 64 72 61 77 7e 6e 22 29 0a 09 65 6e  s a draw~n")..en
2770: 64 2c 0a 09 48 65 61 64 77 69 6e 64 5f 70 65 72  d,..Headwind_per
2780: 63 65 6e 74 20 3d 20 72 6f 75 6e 64 28 28 53 75  cent = round((Su
2790: 6d 5f 6f 66 5f 68 65 61 64 77 69 6e 64 5f 64 69  m_of_headwind_di
27a0: 73 74 61 6e 63 65 73 2f 54 6f 74 61 6c 5f 64 69  stances/Total_di
27b0: 73 74 61 6e 63 65 29 2a 31 30 30 2c 20 32 29 2c  stance)*100, 2),
27c0: 0a 09 53 69 64 65 77 69 6e 64 5f 70 65 72 63 65  ..Sidewind_perce
27d0: 6e 74 20 3d 20 72 6f 75 6e 64 28 28 53 75 6d 5f  nt = round((Sum_
27e0: 6f 66 5f 73 69 64 65 77 69 6e 64 5f 64 69 73 74  of_sidewind_dist
27f0: 61 6e 63 65 73 2f 54 6f 74 61 6c 5f 64 69 73 74  ances/Total_dist
2800: 61 6e 63 65 29 2a 31 30 30 2c 20 32 29 2c 0a 09  ance)*100, 2),..
2810: 54 61 69 6c 77 69 6e 64 5f 70 65 72 63 65 6e 74  Tailwind_percent
2820: 20 3d 20 72 6f 75 6e 64 28 28 53 75 6d 5f 6f 66   = round((Sum_of
2830: 5f 74 61 69 6c 77 69 6e 64 5f 64 69 73 74 61 6e  _tailwind_distan
2840: 63 65 73 2f 54 6f 74 61 6c 5f 64 69 73 74 61 6e  ces/Total_distan
2850: 63 65 29 2a 31 30 30 2c 20 32 29 2c 0a 09 69 6f  ce)*100, 2),..io
2860: 3a 66 6f 72 6d 61 74 28 22 7e 77 25 20 48 65 61  :format("~w% Hea
2870: 64 77 69 6e 64 7e 6e 7e 77 25 20 53 69 64 65 77  dwind~n~w% Sidew
2880: 69 6e 64 7e 6e 7e 77 25 20 54 61 69 6c 77 69 6e  ind~n~w% Tailwin
2890: 64 7e 6e 22 2c 20 5b 48 65 61 64 77 69 6e 64 5f  d~n", [Headwind_
28a0: 70 65 72 63 65 6e 74 2c 20 53 69 64 65 77 69 6e  percent, Sidewin
28b0: 64 5f 70 65 72 63 65 6e 74 2c 20 54 61 69 6c 77  d_percent, Tailw
28c0: 69 6e 64 5f 70 65 72 63 65 6e 74 5d 29 2c 0a 25  ind_percent]),.%
28d0: 0a 09 69 6f 3a 66 6f 72 6d 61 74 28 22 44 69 72  ..io:format("Dir
28e0: 65 63 74 69 6f 6e 3a 20 7e 73 7e 6e 53 70 65 65  ection: ~s~nSpee
28f0: 64 3a 20 7e 73 20 6d 70 68 7e 6e 47 75 73 74 3a  d: ~s mph~nGust:
2900: 20 7e 73 20 6d 70 68 7e 6e 57 65 61 74 68 65 72   ~s mph~nWeather
2910: 20 74 79 70 65 3a 20 7e 73 7e 6e 54 65 6d 70 65   type: ~s~nTempe
2920: 72 61 74 75 72 65 3a 20 7e 73 20 64 65 67 20 43  rature: ~s deg C
2930: 7e 6e 22 2c 20 5b 44 69 72 65 63 74 69 6f 6e 2c  ~n", [Direction,
2940: 20 53 70 65 65 64 2c 20 47 75 73 74 2c 20 57 65   Speed, Gust, We
2950: 61 74 68 65 72 5f 74 79 70 65 2c 20 54 65 6d 70  ather_type, Temp
2960: 65 72 61 74 75 72 65 5d 29 2e 0a 0a 0a 25 4e 65  erature])....%Ne
2970: 65 64 20 74 6f 20 72 65 61 64 20 41 50 49 20 6b  ed to read API k
2980: 65 79 20 66 72 6f 6d 20 66 69 6c 65 0a 72 65 61  ey from file.rea
2990: 64 61 70 69 6b 65 79 28 29 20 2d 3e 0a 09 7b 5f  dapikey() ->..{_
29a0: 53 74 61 74 75 73 2c 20 4b 65 79 7d 20 3d 20 66  Status, Key} = f
29b0: 69 6c 65 3a 72 65 61 64 5f 66 69 6c 65 28 6f 73  ile:read_file(os
29c0: 3a 67 65 74 65 6e 76 28 22 48 4f 4d 45 22 29 20  :getenv("HOME") 
29d0: 2b 2b 20 22 2f 2e 64 61 74 61 70 6f 69 6e 74 22  ++ "/.datapoint"
29e0: 29 2c 0a 09 73 74 72 69 6e 67 3a 73 74 72 69 70  ),..string:strip
29f0: 28 65 72 6c 61 6e 67 3a 62 69 6e 61 72 79 5f 74  (erlang:binary_t
2a00: 6f 5f 6c 69 73 74 28 4b 65 79 29 2c 72 69 67 68  o_list(Key),righ
2a10: 74 2c 24 5c 6e 29 2e 0a                          t,$\n)..