├── 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 |
--------------------------------------------------------------------------------