├── config ├── sys.config └── vm.args ├── attach.sh ├── rebar3 ├── get_odds2.sh ├── js ├── favicon.ico ├── example.html ├── example.js └── rpc.js ├── start.sh ├── todo ├── get_odds.sh ├── .gitignore ├── apps └── odds_scraper │ └── src │ ├── odds_scraper.app.src │ ├── cron.erl │ ├── odds_scraper_app.erl │ ├── odds_scraper_sup.erl │ ├── http_handler.erl │ ├── file_handler.erl │ ├── talker.erl │ └── sportsbookreview.erl ├── rebar.config └── README.md /config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | {odds_scraper, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /attach.sh: -------------------------------------------------------------------------------- 1 | ./_build/prod/rel/odds_scraper/bin/odds_scraper attach 2 | -------------------------------------------------------------------------------- /rebar3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zack-bitcoin/odds-scraper/master/rebar3 -------------------------------------------------------------------------------- /get_odds2.sh: -------------------------------------------------------------------------------- 1 | lynx -dump https://classic.sportsbookreview.com/betting-odds/money-line/ 2 | -------------------------------------------------------------------------------- /js/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zack-bitcoin/odds-scraper/master/js/favicon.ico -------------------------------------------------------------------------------- /config/vm.args: -------------------------------------------------------------------------------- 1 | -sname odds_scraper 2 | 3 | -setcookie odds_scraper_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | ./rebar3 compile 2 | ./rebar3 as prod release 3 | ./_build/prod/rel/odds_scraper/bin/odds_scraper start 4 | -------------------------------------------------------------------------------- /todo: -------------------------------------------------------------------------------- 1 | Todo 2 | ======= 3 | 4 | Make a javascript library to decode the api response. 5 | - not all the data is being displayed. 6 | 7 | it crashes sometimes. 8 | 9 | -------------------------------------------------------------------------------- /get_odds.sh: -------------------------------------------------------------------------------- 1 | lynx -dump https://classic.sportsbookreview.com/betting-odds/money-line/ > sportsbookreview 2 | 3 | # https://www.actionnetwork.com/odds 4 | # https://www.oddsshark.com/nfl/odds 5 | -------------------------------------------------------------------------------- /js/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .edts 3 | *.iml 4 | _build 5 | /rel/ 6 | *.db 7 | *~ 8 | .#* 9 | \#* 10 | .rebar 11 | erl_crash.dump 12 | keys_backup 13 | lib/ 14 | bin/ 15 | .Python 16 | include/ 17 | *.pyc 18 | nosetests.xml 19 | pip-selfcheck.json 20 | config/*/sys.config 21 | man 22 | compile_commands.json 23 | deps/* 24 | rebar.lock 25 | .DS_Store 26 | sys.config.tmpl 27 | sportsbookreview -------------------------------------------------------------------------------- /apps/odds_scraper/src/odds_scraper.app.src: -------------------------------------------------------------------------------- 1 | {application, odds_scraper, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, {odds_scraper_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib, 9 | ssl, 10 | cowboy, 11 | inets, 12 | jiffy, 13 | encrypter 14 | ]}, 15 | {env,[]}, 16 | {modules, []}, 17 | {links, []} 18 | ]}. 19 | -------------------------------------------------------------------------------- /rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, [ 3 | {jiffy, "1.0.0", {git, "https://github.com/davisp/jiffy", {tag, "1.0.0"}}}, 4 | {cowboy, "2.6.0", {git, "https://github.com/ninenines/cowboy.git", {tag, "2.6.0"}}}, 5 | {encrypter, "1", {git, "https://github.com/zack-bitcoin/encrypter", {tag, "master"}}} 6 | ]}. 7 | 8 | {relx, [{release, {odds_scraper, "0.1.0"}, 9 | [odds_scraper, 10 | sasl]}, 11 | 12 | {sys_config, "./config/sys.config"}, 13 | {vm_args, "./config/vm.args"}, 14 | 15 | {dev_mode, true}, 16 | {include_erts, false}, 17 | 18 | {extended_start_script, true}] 19 | }. 20 | 21 | {profiles, [{prod, [{relx, [{dev_mode, false}, 22 | {include_erts, true}]}] 23 | }] 24 | }. 25 | -------------------------------------------------------------------------------- /apps/odds_scraper/src/cron.erl: -------------------------------------------------------------------------------- 1 | -module(cron). 2 | -export([doit/0, doit/1, reload/0]). 3 | 4 | %We want to re-download from the website every time the full node finds a new block. and re-generage the JSON. 5 | 6 | -define(MinRequestPeriod, 20000).%20 seconds 7 | -define(BlockCheckPeriod, 2000).%2 seconds 8 | 9 | 10 | reload() -> 11 | io:fwrite("reload"), 12 | os:cmd("sh ../../../../get_odds2.sh > ../../../../sportsbookreview"), 13 | timer:sleep(3000), 14 | sportsbookreview:reload(). 15 | talk(X) -> 16 | talker:talk(X, {{127,0,0,1}, 8081}). 17 | doit(N) -> 18 | spawn(fun() -> loop(N) end). 19 | doit() -> doit(0). 20 | loop(N) -> 21 | %look up current block height. if it is bigger than n, we need to reload. 22 | {ok, M} = talk({height}), 23 | case M of 24 | N -> timer:sleep(?BlockCheckPeriod); 25 | _ -> 26 | spawn(fun() -> reload() end), 27 | timer:sleep(?MinRequestPeriod) 28 | end, 29 | loop(M). 30 | -------------------------------------------------------------------------------- /apps/odds_scraper/src/odds_scraper_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc odds_scraper public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(odds_scraper_app). 7 | 8 | -behaviour(application). 9 | 10 | -export([start/2, stop/1]). 11 | 12 | start(_StartType, _StartArgs) -> 13 | inets:start(), 14 | start_http(), 15 | %cron:doit(0), 16 | odds_scraper_sup:start_link(). 17 | 18 | stop(_State) -> 19 | ok. 20 | 21 | %% internal functions 22 | start_http() -> 23 | Dispatch = 24 | cowboy_router:compile( 25 | [{'_', [ 26 | {"/:file", file_handler, []},%, 27 | %{"/[...]", file_handler, []}%, 28 | {"/", http_handler, []} 29 | ]}]), 30 | %{ok, Port} = application:get_env(amoveo_mining_pool, port), 31 | Port = 8084, 32 | {ok, _} = cowboy:start_clear(http, 33 | [{ip, {0,0,0,0}}, {port, Port}], 34 | #{env => #{dispatch => Dispatch}}), 35 | ok. 36 | 37 | -------------------------------------------------------------------------------- /js/example.js: -------------------------------------------------------------------------------- 1 | (async function(){ 2 | 3 | 4 | //first off, looking up the IP address and port for the server. This part could potentially be a hard IP and port, if you plan to always use the api served from the same place. 5 | const server_ip = document.URL.split("/")[2].split(":")[0]; 6 | var URL_REGEX = /^(https?)?(?:[\:\/]*)([a-z0-9\.-]*)(?:\:([0-9]+))?(\/[^?#]*)?(?:\?([^#]*))?(?:#(.*))?$/i; 7 | var match = document.URL.match(URL_REGEX); 8 | var server_port = match[3]; 9 | async function apost(x) { 10 | return rpc.apost(x, server_ip, server_port); 11 | }; 12 | 13 | 14 | 15 | var page = document.getElementById("page"); 16 | 17 | //page.innerHTML = "

Success.

"; 18 | const response = await apost(["test", 3]); 19 | const result = response.slice(1).map( 20 | function(x){ 21 | return(x.slice(1).map( 22 | function(y){ 23 | return(atob(y)) 24 | })); 25 | }); 26 | console.log(JSON.stringify(result)); 27 | //console.log(JSON.stringify(response.slice(1).map(function(x){return(atob(x))}))); 28 | 29 | //var response2 = response.slice(1) 30 | //console.log(JSON.stringify(response2)); 31 | //var r2 = response2.map(function(x){ 32 | // return(atob(x))}); 33 | //console.log(JSON.stringify(r2)); 34 | //console.log(atob(response[1])); 35 | //console.log(atob(response[2])); 36 | //console.log(atob(response[3])); 37 | 38 | })(); 39 | -------------------------------------------------------------------------------- /apps/odds_scraper/src/odds_scraper_sup.erl: -------------------------------------------------------------------------------- 1 | -module(odds_scraper_sup). 2 | -behaviour(supervisor). 3 | -export([start_link/0]). 4 | -export([init/1, stop/0]). 5 | -define(SERVER, ?MODULE). 6 | -define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}). 7 | 8 | %-define(CHILD(I, TYPE), #{id => 9 | 10 | -define(keys, [sportsbookreview 11 | ]). 12 | 13 | start_link() -> 14 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 15 | child_killer([]) -> []; 16 | child_killer([H|T]) -> 17 | supervisor:terminate_child(amoveo_explorer_sup, H), 18 | child_killer(T). 19 | stop() -> child_killer(?keys). 20 | child_maker([]) -> []; 21 | child_maker([H|T]) -> [?CHILD(H, worker)|child_maker(T)]. 22 | 23 | %% sup_flags() = #{strategy => strategy(), % optional 24 | %% intensity => non_neg_integer(), % optional 25 | %% period => pos_integer()} % optional 26 | %% child_spec() = #{id => child_id(), % mandatory 27 | %% start => mfargs(), % mandatory 28 | %% restart => restart(), % optional 29 | %% shutdown => shutdown(), % optional 30 | %% type => worker(), % optional 31 | %% modules => modules()} % optional 32 | init([]) -> 33 | SupFlags = #{strategy => one_for_all, 34 | intensity => 0, 35 | period => 1}, 36 | %ChildSpecs = [], 37 | ChildSpecs = child_maker(?keys), 38 | {ok, {SupFlags, ChildSpecs}}. 39 | 40 | %% internal functions 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Odds Scraper 2 | ======= 3 | 4 | You need lynx installed to use this software. 5 | Tested in Ubuntu 20.04 6 | 7 | `sh get_odds.sh` loading the web page to a local file. 8 | 9 | `sh start.sh` to turn on the server. 10 | 11 | `sh attach.sh` to connect to the server's REPL. 12 | 13 | hold the control key and click the D key to disconnect from the REPL. 14 | 15 | 16 | While connected to REPL you can issue these commands 17 | ================ 18 | 19 | `halt().` to turn it off. 20 | 21 | `cron:doit()` to automatically refresh the betting odds, every time a block is added to the Amoveo blockchain. This only works if there is an Amoveo full node running on the same computer and it is using port 8081 for it's internal API. 22 | 23 | `sportsbookreview:reload()` to read the html of the sportsbookreview website from a local file where 'get_odds.sh' had stored it. Convert it to JSON. 24 | 25 | `sportsbookreview:read()` returns a stored copy of the JSON version of the data from the sports book review website. 26 | 27 | using the api 28 | =========== 29 | 30 | `curl -i -d '["test", 1]' http://localhost:8084` 31 | 32 | when you load the data from the api, all the words are base64 encoded. 33 | you can base64 decode in javascript like this: 34 | `Decoded = atob(Encoded);` 35 | 36 | Here is example code of using javascript to decode what you get from the server, stored in the variable `DATA`. 37 | 38 | ``` 39 | DATA 40 | .slice(1) 41 | .map(function(x){ 42 | return(atob(x)); 43 | }); 44 | ``` 45 | 46 | You can see it in context in the included [example javascript code.](js/example.js) 47 | -------------------------------------------------------------------------------- /js/rpc.js: -------------------------------------------------------------------------------- 1 | var rpc = (function() { 2 | function url(port, ip) { 3 | return "http://".concat(ip).concat(":"). 4 | concat(port.toString()).concat("/"); } 5 | function messenger(cmd, callback){ 6 | var u = url(8088, get_ip()); 7 | return talk(cmd, u, callback, 10000); 8 | }; 9 | async function main2(cmd, ip, port) { 10 | if (ip == undefined){ 11 | ip = get_ip(); 12 | } 13 | if (port == undefined){ 14 | port = get_port(); 15 | } 16 | var u = url(port, ip); 17 | return atalk(cmd, u);//use up to 10 seconds for this request 18 | } 19 | async function atalk(cmd, u) { 20 | return new Promise(function(resolve, reject){ 21 | let xmlhttp = new XMLHttpRequest(); 22 | xmlhttp.open("POST", u); 23 | xmlhttp.onload = function() { 24 | if (this.status >= 200 && this.status < 300) { 25 | resolve(JSON.parse(xmlhttp.response)[1]); 26 | } else { 27 | reject({ 28 | status: this.status, 29 | statusText: xmlhttp.statusText 30 | }); 31 | } 32 | }; 33 | xmlhttp.onerror = function () { 34 | reject({ 35 | status: this.status, 36 | statusText: xmlhttp.statusText 37 | }); 38 | }; 39 | xmlhttp.send(JSON.stringify(cmd)); 40 | }); 41 | }; 42 | return { 43 | apost: main2 44 | }; 45 | })(); 46 | -------------------------------------------------------------------------------- /apps/odds_scraper/src/http_handler.erl: -------------------------------------------------------------------------------- 1 | -module(http_handler). 2 | 3 | -export([init/2, init/3, handle/2, terminate/3, doit/1]). 4 | 5 | %curl -i -d '[-6,"test", 1]' http://localhost:8084 6 | 7 | init(Req, State) -> 8 | handle(Req, State). 9 | handle(Req, State) -> 10 | {ok, Data, _} = cowboy_req:read_body(Req), 11 | true = is_binary(Data), 12 | A = packer:unpack(Data), 13 | B = doit(A), 14 | D = packer:pack(B), 15 | Headers = #{<<"content-type">> => <<"application/octet-stream">>, 16 | <<"Access-Control-Allow-Origin">> => <<"*">>}, 17 | Req2 = cowboy_req:reply(200, Headers, D, Req), 18 | {ok, Req2, State}. 19 | init(_Type, Req, _Opts) -> {ok, Req, no_state}. 20 | terminate(_Reason, _Req, _State) -> ok. 21 | doit({test, 1}) -> 22 | %reverse order. 23 | LoT = sportsbookreview:read(),%list of tuples 24 | LoL = lists:map(fun(X) -> 25 | tuple_to_list(X) 26 | end, LoT), 27 | Lo1 = lists:foldl(fun(A, B) -> 28 | A ++ B 29 | end, [], LoL), 30 | {ok, Lo1}; 31 | doit({test, 2}) -> 32 | %good order 33 | LoT = sportsbookreview:read(),%list of tuples 34 | LoL = lists:map(fun(X) -> 35 | tuple_to_list(X) 36 | end, LoT), 37 | Lo1 = lists:foldl(fun(A, B) -> 38 | B ++ A 39 | end, [], LoL), 40 | {ok, Lo1}; 41 | doit({test, 3}) -> 42 | %sublists for each sport. 43 | LoT = sportsbookreview:read(),%list of tuples 44 | LoL = lists:map(fun(X) -> 45 | tuple_to_list(X) 46 | end, LoT), 47 | {ok, LoL}. 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /apps/odds_scraper/src/file_handler.erl: -------------------------------------------------------------------------------- 1 | 2 | -module(file_handler). 3 | 4 | -export([init/2, init/3, handle/2, terminate/3]). 5 | %example of talking to this handler: 6 | %httpc:request(post, {"http://127.0.0.1:3011/", [], "application/octet-stream", "echo"}, [], []). 7 | %curl -i -d '[-6,"test"]' http://localhost:3011 8 | init(Req, Opts) -> 9 | handle(Req, Opts). 10 | handle(Req, State) -> 11 | F0 = cowboy_req:path(Req), 12 | PrivDir0 = "../../../../js", 13 | PrivDir = list_to_binary(PrivDir0), 14 | F = case F0 of 15 | <<"/example.html">> -> <<"/example.html">>; 16 | <<"/example.js">> -> <<"/example.js">>; 17 | <<"/favicon.ico">> -> F0; 18 | %<<"/codecBytes.js">> -> F0; 19 | %<<"/crypto.js">> -> F0; 20 | %<<"/format.js">> -> F0; 21 | %<<"/signing.js">> -> F0; 22 | <<"/rpc.js">> -> F0; 23 | X -> 24 | io:fwrite("ext file handler block access to: "), 25 | io:fwrite(X), 26 | io:fwrite("\n"), 27 | <<"/example.html">> 28 | end, 29 | %File = << PrivDir/binary, <<"/external_web">>/binary, F/binary>>, 30 | File = << PrivDir/binary, F/binary>>, 31 | {ok, _Data, _} = cowboy_req:read_body(Req), 32 | Headers = #{<<"content-type">> => <<"text/html">>, 33 | <<"Access-Control-Allow-Origin">> => <<"*">>}, 34 | Text = read_file(File), 35 | Req2 = cowboy_req:reply(200, Headers, Text, Req), 36 | {ok, Req2, State}. 37 | read_file(F) -> 38 | case file:open(F, [read, binary, raw]) of 39 | {ok, File } -> 40 | {ok, O} =file:pread(File, 0, filelib:file_size(F)), 41 | file:close(File), 42 | O; 43 | {error, enoent} -> 44 | io:fwrite("file does not exist "), 45 | io:fwrite(F), 46 | io:fwrite("\n"), 47 | error 48 | end. 49 | %{ok, File } = file:open(F, [read, binary, raw]), 50 | %{ok, O} =file:pread(File, 0, filelib:file_size(F)), 51 | %file:close(File), 52 | %O. 53 | init(_Type, Req, _Opts) -> {ok, Req, []}. 54 | terminate(_Reason, _Req, _State) -> ok. 55 | -------------------------------------------------------------------------------- /apps/odds_scraper/src/talker.erl: -------------------------------------------------------------------------------- 1 | -module(talker). 2 | -export([talk/2, talk/3, talk_timeout/3]). 3 | 4 | -define(RETRY, 3). 5 | 6 | talk_timeout(Msg, {IP, Port}, X) -> 7 | P = build_string_peer(IP, Port), 8 | talk_helper(Msg, P, ?RETRY, X). 9 | 10 | talk(Msg, {IP, Port}) -> 11 | talk(Msg, build_string_peer(IP, Port)); 12 | 13 | talk(Msg, Peer) -> 14 | talk_helper(Msg, Peer, ?RETRY, 20000). 15 | 16 | talk(Msg, IP, Port) -> 17 | talk(Msg, build_string_peer(IP, Port)). 18 | ip2string2(X) -> 19 | (integer_to_list(X)) ++ ("."). 20 | ip2string([A,B,C,D]) -> 21 | ip2string({A,B,C,D}); 22 | ip2string({A,B,C,D}) -> 23 | ip2string2(A) ++ 24 | ip2string2(B) ++ 25 | ip2string2(C) ++ 26 | integer_to_list(D). 27 | build_string_peer(IP, Port) -> 28 | T = ip2string(IP), 29 | P = integer_to_list(Port), 30 | "http://" ++ T ++ ":" ++ P ++ "/". 31 | check_print(S) -> 32 | io:fwrite(S). 33 | % case sync_mode:check() of 34 | % normal -> ok; 35 | % quick -> io:fwrite(S) 36 | % end. 37 | 38 | talk_helper(_, _, 0, _) -> 39 | check_print("talk helper fail\n"), 40 | bad_peer; 41 | %{error, failed_connect}; 42 | talk_helper(Msg, Peer, N, TimeOut) -> 43 | PM = packer:pack(Msg), 44 | %check_print("sending message "), 45 | %check_print(PM), 46 | %check_print("\n"), 47 | %timer:sleep(500), 48 | Msg = packer:unpack(PM), 49 | case httpc:request(post, {Peer, [], "application/octet-stream", iolist_to_binary(PM)}, [{timeout, TimeOut}], []) of 50 | {ok, {{_, 500, _}, _Headers, []}} -> 51 | check_print("server crashed. Will ignore peer. "), 52 | check_print(element(1, Msg)), 53 | check_print(" \n"), 54 | bad_peer; 55 | %talk_helper(Msg, Peer, 0, TimeOut); 56 | {ok, {Status, _Headers, []}} -> 57 | check_print("talk_helper weird response. Attempting to reconnect. \n"), 58 | check_print(packer:pack(Status)), 59 | talk_helper(Msg, Peer, N - 1, TimeOut); 60 | {ok, {_, _, R}} -> 61 | %check_print("talker peer is "), 62 | %check_print(Peer), 63 | %check_print("\n"), 64 | %check_print("talker msg is "), 65 | %check_print(packer:pack(Msg)), 66 | %check_print("\n"), 67 | %check_print("talker response is "), 68 | %check_print(R), 69 | %check_print("\n"), 70 | DoubleOK = packer:pack({ok, ok}), 71 | if 72 | R == DoubleOK -> 0; 73 | true -> 74 | packer:unpack(R) 75 | end; 76 | {error, socket_closed_remotely} -> 77 | %check_print("talk_helper socket closed remotely. attempting to reconnect \n"), 78 | talk_helper(Msg, Peer, N - 1, TimeOut); 79 | {error, timeout} -> 80 | check_print("talk_helper timeout. attempting to reconnect \n"), 81 | check_print(element(1, Msg)), 82 | check_print("\n"), 83 | talk_helper(Msg, Peer, N - 1, TimeOut); 84 | {error, failed_connect} -> 85 | check_print("talk_helper failed_connect 0. will ignore this peer. \n"), 86 | bad_peer; 87 | %talk_helper(Msg, Peer, N - 1, TimeOut); 88 | {error, {failed_connect, _}} -> 89 | %check_print("talk_helper failed_connect 1. will ignore this peer. \n"), 90 | %check_print(PM), 91 | bad_peer; 92 | %talk_helper(Msg, Peer, N - 1, TimeOut); 93 | X -> check_print("talk helper unexpected error"), 94 | check_print(X), 95 | error 96 | end. 97 | -------------------------------------------------------------------------------- /apps/odds_scraper/src/sportsbookreview.erl: -------------------------------------------------------------------------------- 1 | -module(sportsbookreview). 2 | -behaviour(gen_server). 3 | -export([start_link/0,code_change/3,handle_call/3,handle_cast/2,handle_info/2,init/1,terminate/2, 4 | reload/0, read/0 5 | ]). 6 | init(ok) -> {ok, []}. 7 | start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, ok, []). 8 | code_change(_OldVsn, State, _Extra) -> {ok, State}. 9 | terminate(_, _) -> io:format("died!"), ok. 10 | handle_info(_, X) -> {noreply, X}. 11 | handle_cast(reload, X) -> 12 | {noreply, reload2(X)}; 13 | handle_cast(_, X) -> {noreply, X}. 14 | handle_call(read, _From, X) -> 15 | {reply, X, X}; 16 | handle_call(_, _From, X) -> {reply, X, X}. 17 | 18 | reload() -> 19 | gen_server:cast(?MODULE, reload). 20 | read() -> 21 | gen_server:call(?MODULE, read). 22 | 23 | reload2(DB) -> 24 | %os:cmd("sh ../../../../get_odds.sh"), 25 | {ok, F} = file:read_file("../../../../sportsbookreview"), 26 | case F of 27 | <<"Server Error", _/binary>> -> 28 | DB; 29 | _ -> 30 | {match, [_|TableEnds0]} = re:run(F, " \\[\\d+\\][^\n]+\n Opener", [global, {capture, all}]), 31 | {match, Dates1} = re:run(F, " Opener\n [^\n]+\n", [global, {capture, all, binary}]), 32 | Dates = lists:map(fun(T) -> 33 | T2 = re:replace(T, " Opener\n ", ""), 34 | iolist_to_binary(T2) 35 | end, Dates1), 36 | 37 | TableEnds = lists:map(fun([{X, _}]) -> X end, TableEnds0), 38 | Tables = cut_tables(TableEnds, F), 39 | Titles = 40 | lists:map(fun(X) -> 41 | {match, [[L]]} = re:run(X, " \\[\\d+\\][^\n]+\n Opener", [global, {capture, all, binary}]), 42 | L2 = re:replace(L, "\n Opener", ""), 43 | L3 = re:replace(L2, " \\[\\d+\\]", ""), 44 | iolist_to_binary(L3) 45 | end, Tables), 46 | %io:fwrite("before tables\n"), 47 | %io:fwrite(Tables), 48 | %io:fwrite("\n"), 49 | %io:fwrite("after tables \n"), 50 | Games = 51 | lists:map( 52 | fun(X) -> 53 | case re:run(X, "[^\n]+\n (\\(\\d+\\) )?\\[\\d+\\][^\n]+\n([^\n]+\n)? \\(BUTTON\\) Options\n((?=(?!eventLink))[\\w\\W])*", [global, {capture, all, binary}]) of 54 | nomatch -> 55 | io:fwrite("nomatch\n"), 56 | io:fwrite(X), 57 | io:fwrite("no match end\n"), 58 | io:fwrite("\n"), 59 | DB; 60 | {match, L} -> 61 | L2 = lists:map( 62 | fun([Game|_]) -> 63 | Game2a = iolist_to_binary(re:replace(Game, "\n\n", "\n", [global])), 64 | {match, Game2b} = re:run(Game2a, "((?=(?!18.. Gamble Responsibly))[\\w\\W])*", [{capture, all, binary}]), 65 | Game2c = iolist_to_binary(Game2b), 66 | Game2 = iolist_to_binary(re:replace(Game2c, " ", "", [global])), 67 | Game3 = iolist_to_binary(re:replace(Game2, "\\[\\d+\\]", "", [global])), 68 | Game4 = iolist_to_binary(re:replace(Game3, "\\(BUTTON\\) Options\n", "", [global])), 69 | Game5 = iolist_to_binary(re:replace(Game4, "\n$", "", [global])), 70 | Game6 = iolist_to_binary(re:replace(Game5, "\n", ", ", [global])), 71 | Game7 = iolist_to_binary(re:replace(Game6, ", \\]$", "", [global])), 72 | Game8 = iolist_to_binary(re:replace(Game7, " \\(\\d+\\)", "", [global])), 73 | Game9 = iolist_to_binary(re:replace(Game8, ", \\[ \\]", "", [global])), 74 | Game10 = iolist_to_binary(re:replace(Game9, ", Final", "", [global])), 75 | Game11 = iolist_to_binary(re:replace(Game10, ", 00", "", [global])), 76 | Game12 = iolist_to_binary(re:replace(Game11, " -, Time", "", [global])), 77 | %io:fwrite("round \n"), 78 | %io:fwrite(iolist_to_binary(Game7)), 79 | %io:fwrite("\n"), 80 | [Game12, "; "] 81 | 82 | %binary:split(Game4, <<"\n">>, [global]) 83 | end, L), 84 | iolist_to_binary(L2) 85 | end 86 | end, Tables), 87 | Result = 88 | lists:zipwith3( 89 | fun(T, Gs, D) -> 90 | {T, Gs, D} 91 | end, Titles, Games, Dates), 92 | %{NowA, NowB, NowC} = erlang:now(), 93 | Result ++ [erlang:now()] 94 | end. 95 | %Games. 96 | 97 | split(Loc, Binary) -> 98 | L8 = Loc*8, 99 | <> = Binary, 100 | {<>, B2}. 101 | 102 | cut_tables([H|T], F) -> 103 | {A, _} = split(H, F), 104 | [A|cut_tables2([H|T], F)]. 105 | cut_tables2([X], F) -> 106 | {_, B} = split(X, F), 107 | [B]; 108 | cut_tables2([A, B|T], F) -> 109 | {X, _} = split(B, F), 110 | {_, H} = split(A, X), 111 | [H|cut_tables2([B|T], F)]. 112 | 113 | 114 | 115 | unused() -> 116 | F = 0, 117 | {match, L} = re:run(F, "\\[\\d{1,4}\\][^\n|]+\n \\d{1,4}\n \\[\\d{1,4}\\][^\n|]+\n[^\n]+\n[^\n]+\n[^\n]+\n[^\n]+\n[^\n]+\n[^\n]+\n[^\n]+\n[^\n]+\n[^\n]+\n[^\n]+\n[^\n]+\n", [global, {capture, all, binary}]), 118 | L2 = lists:map(fun(X) -> 119 | A = iolist_to_binary(re:replace(hd(X), "\n[^\n]+\n", "")), 120 | B = iolist_to_binary(re:replace(A, "\n[^\n]+\n", "")), 121 | Y = iolist_to_binary(re:replace(B, "\n", <<"">>, [global])), 122 | iolist_to_binary(re:replace(Y, "\\[\\d+\\]", "", [global])) 123 | end, L), 124 | L2. 125 | 126 | 127 | --------------------------------------------------------------------------------