163 Commits

Author SHA1 Message Date
Dev Singh
df37947b21 Merge branch 'competition' 2023-03-17 10:11:56 -05:00
Dev Singh
8e6c44db65 updates for 2023ilpe 2023-03-17 10:09:48 -05:00
Dev
11398290eb fix 2022-04-08 15:40:33 -05:00
Dev
d847f6d6a7 hi 2022-04-08 15:20:41 -05:00
Dev Singh
b5c8a91fad update data.py for new metrics structure 2022-03-30 01:30:55 -05:00
Dev Singh
8e5fa7eace reintroduce cutoff usage 2022-03-29 18:43:28 -05:00
Arthur Lu
69c6059ff8 added result logging for metric module 2022-03-29 21:17:58 +00:00
Dev Singh
fdcdadb8b2 only use gl2 2022-03-28 23:17:25 -05:00
Arthur Lu
cdd81295fc commented metrics in module.py 2022-03-28 22:02:39 +00:00
Dev Singh
82ec2d85cc clear metrics only on script start 2022-03-28 15:47:46 -05:00
Dev Singh
ac8002aaf8 delete on start 2022-03-28 14:43:24 -05:00
Dev Singh
25e4babd71 Revert "experimental trueskill support"
This reverts commit 3fe2922e97.
2022-03-28 14:21:23 -05:00
Dev Singh
3fe2922e97 experimental trueskill support 2022-03-28 10:13:42 -05:00
Dev
9752fd323b remove time check 2022-03-25 13:39:24 -05:00
Dev
ef63c1de7e add ability to load manual JSON for metrics 2022-03-24 16:19:47 -05:00
Dev
8908f05cbe fix prod issues 2022-03-16 18:51:10 -05:00
Dev
143218dda3 split sbatch commands 2022-03-16 18:39:30 -05:00
Dev
def2fc9b73 change gitignore, add up submit
Former-commit-id: 927f0a1a4c3dd0aff6fb4fca5f99ea62bc61584f
2022-03-14 20:55:00 -05:00
Dev
e8a5bb75f8 add sbatch script
Former-commit-id: f521f7b3f69df71171cd046a40bcbcb6637967a6
2022-03-13 21:56:34 -05:00
Arthur Lu
c9dd09f5e9 fixed file name
Former-commit-id: 7d113b378854316c3af5e5c58f589c5c062040b4
2022-03-13 18:54:50 -07:00
Arthur Lu
3c6e3ac58e added pandas to requirements,
readded dev docker files


Former-commit-id: 3fa4ef57e5e9542ce245ab0ef9b8320e21c9507c
2022-03-14 01:53:50 +00:00
Arthur Lu
8c28c24d60 removed all unessasary files,
moved important files to folder "competition"


Former-commit-id: 59becb22abc3305a36e2876351e6c7306e3f551e
2022-03-14 01:33:24 +00:00
Arthur Lu
4836f48a34 pyinstaller onedir workaround for requests issue,
moved spec file to build folder


Former-commit-id: 4427eba5c993222cd2ebfdfc76a4685e25e18b0c
2022-02-24 02:56:08 +00:00
Arthur Lu
9a1a45f1c9 removed cert verification for requests library
Former-commit-id: 4914b98a21478a10be7d2f737dd6d5669b4c5681
2022-02-20 23:38:18 +00:00
Arthur Lu
d7ed695ad1 fixed build script,
added binutils to docker container for build requirements,
added required scipy modules to superscript.spec


Former-commit-id: 60a6fc1106dc90514bd1270138ab9166efa29290
2022-02-20 23:16:02 +00:00
Arthur Lu
21d92e65b2 add binary paths to devcontainer.json
Former-commit-id: a323f3161d6ea326b0215d5ed5ebbadae0f38597
2022-02-20 22:53:11 +00:00
Arthur Lu
0cace3cec3 improved exit code reporting
Former-commit-id: f36f45bc6a2773b8a821d0e046ce1b47fc4ced0f
2022-02-19 23:29:58 +00:00
Arthur Lu
80b63269df readded zmq messaging
Former-commit-id: e38653c4dc4ffe6aada19cac2251c3ec28bfbc2b
2022-02-19 22:58:58 +00:00
Arthur Lu
56447603e1 implemented logger,
dropped zmq because of constant inconsistency,
daemon process now outputs to file,
deleted client.py


Former-commit-id: d3251e5f6404d0dce42da49e5d577651e718e168
2022-02-19 08:52:49 +00:00
Arthur Lu
2130182212 fixed pull APIError calls (removed endpoint arg)
Former-commit-id: 5090eefdbd5b13bfda285d5480e79896dd3610a5
2022-02-19 06:50:34 +00:00
Arthur Lu
b1eff19ea4 removec __all__ property from superscript
Former-commit-id: 67c4684b5943467cc07b8cc638dc438ad0ee3e54
2022-02-19 06:46:39 +00:00
Arthur Lu
b43836899d moved config functions into Configuration class,
simplified exception class by removing error codes,
removed exec_threads from module parameters


Former-commit-id: 545ef765653970e1cdebac692eccd227effb2508
2022-02-19 06:19:13 +00:00
Arthur Lu
524a0a211d removed gui (last commit tagged "gui"),
removed print statement in pit module


Former-commit-id: 4978aee142eaf9431913b44eabfc0dfb79c7b600
2022-02-09 05:36:19 +00:00
Arthur Lu
9c152fb109 Merge pull request #23 from titanscouting/improve-devdocker
switch docker image to python:slim

Former-commit-id: 28b440725d338dd830ac9d3e0905eba54b05811f
2022-02-08 20:17:38 -08:00
Arthur Lu
491508a400 switch docker image to python:slim,
move requirements.txt to .devcontainer/


Former-commit-id: 427a37e514
2022-02-04 08:38:03 +00:00
Arthur Lu
b0ffdbab9a fixed pit processing issue due to config change
Former-commit-id: 15f95b778b
2022-02-04 03:28:08 +00:00
Arthur Lu
c4bb633e08 fixed pit data fetching
Former-commit-id: d017ec52a7
2022-02-04 03:24:47 +00:00
Dev Singh
c46e74036b get team nums at comp
Former-commit-id: 028f6f775d
2022-02-04 03:16:45 +00:00
Arthur Lu
c08d3d3ae7 Merge branch 'superscript-v1' of https://github.com/titanscouting/tra-superscript into superscript-v1
Former-commit-id: 2b72743b27
2022-02-04 03:06:14 +00:00
Arthur Lu
6cfe4e3f33 fixed bugs in data.py to work with database,
fixed object field in module.py: Metric,
fixed timestamp input in superscripy.py


Former-commit-id: 1e18cddc47
2022-02-04 03:06:09 +00:00
Dev Singh
40673169b2 update validation schema
Former-commit-id: 982cb0aa6b
2022-02-04 02:44:48 +00:00
Arthur Lu
7d08194636 patched issue in multiprocessing,
moved ConfigurationError to exceptions.py,
made pull use load_config in config.py


Former-commit-id: aed03369c9
2022-01-10 20:23:14 +00:00
Dev Singh
a940f3ffeb use tab size 4
Former-commit-id: 2f83604e14
2022-01-10 20:02:58 +00:00
Dev Singh
db4b020851 allow overriding competition in config
Former-commit-id: 40252dd74c
2022-01-10 15:40:58 +00:00
Dev Singh
18d4438f7f fix typo
Former-commit-id: e16295da2b
2022-01-10 15:35:06 +00:00
Dev Singh
c77dd1ea5f set tab config
Former-commit-id: 1c3fc9a872
2022-01-10 09:23:43 -06:00
Dev Singh
74542c1d8f add validation schema for persistent keys
Former-commit-id: ceaf3f2891
2022-01-10 09:21:46 -06:00
Dev Singh
b4c9ef22b6 pull some data from API, fix some datatype compats
Former-commit-id: 03ec0dd8fd
2022-01-09 22:19:50 -06:00
Arthur Lu
af74a69579 removed commented out code
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 3669712bec
2021-11-24 02:27:03 +00:00
Arthur Lu
ac66545226 changed Module interface to 3 functions
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 356b71be62
2021-11-23 22:23:59 +00:00
Arthur Lu
4b5db1aba8 moved config parsing functions to config.py
Former-commit-id: a251fef024
2021-11-06 01:50:55 +00:00
Arthur Lu
b9610b7b46 improved and streamlined config error handling
Former-commit-id: 99efefd302
2021-11-06 00:04:11 +00:00
Arthur Lu
14ed3cc507 Merge pull request #19 from titanscouting/modularize
Reflect modularization changes into v1

Former-commit-id: b0a0632b99
2021-11-05 16:22:04 -07:00
Arthur Lu
c90a35ff51 added empty modules for future additions
Former-commit-id: d234302cdc
2021-11-05 23:17:42 +00:00
Arthur Lu
60e88a5987 formalized module interface
Former-commit-id: 108284a94b
2021-11-02 05:37:27 +00:00
Arthur Lu
9c2946718f removed testing notebook,
anticipated removal of pandas requirement,
added pandas and matplotlib to pyinstaller exclusion,
removed unessasary option in build scripts


Former-commit-id: 0fd24d42e1
2021-10-30 03:51:03 +00:00
Arthur Lu
bd0c0d99f9 module replaces processing
Former-commit-id: d798bfe7d2
2021-10-30 03:11:10 +00:00
Arthur Lu
9ddf61621e fixed debug logging
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: bd87111e08
2021-10-28 21:12:28 +00:00
Arthur Lu
0af93238be implemented dynamic module loading/running,
fixed minor issue in metric module

Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 7be48af85e
2021-10-28 20:40:56 +00:00
Arthur Lu
6c8e738420 added Metric, Pit modules (theoretically working)
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 3ac4e96d2d
2021-10-28 20:13:57 +00:00
Arthur Lu
0eccc32096 changed Match module to use current data bindings
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: afab67f8ef
2021-10-22 01:40:56 +00:00
Arthur Lu
f8f8543ea2 changed sample json
Former-commit-id: 8966900341
2021-10-21 22:33:26 +00:00
Arthur Lu
a1fb295a1a minor fix
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 7f0d3fc753
2021-10-21 21:58:02 +00:00
Arthur Lu
4ded02b34f added sample initializaition loop
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: d16fe61a79
2021-10-21 21:56:44 +00:00
Arthur Lu
88282aa18b modified config validation for Match module
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: de81a03e3d
2021-10-21 21:51:14 +00:00
Arthur Lu
66bf3a3a3e removed autovivification (likely not required)
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: f40939d69d
2021-10-21 21:29:44 +00:00
Arthur Lu
375b550153 finished rough outline for Match module
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: d5ebb0348b
2021-10-21 21:27:35 +00:00
Arthur Lu
79dd2c3479 minor fix
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 72a14bfac9
2021-10-21 20:56:06 +00:00
Arthur Lu
d2ced284ea added working load_data for Match module
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 8e8c19c5fd
2021-10-21 20:42:47 +00:00
Arthur Lu
07965cba4b added working validate_config for Match module
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: b9e2de2dc6
2021-10-21 20:28:29 +00:00
Arthur Lu
36081e1239 removed keys
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 4a1d7f0db1
2021-10-21 20:05:07 +00:00
Dev Singh
de4d3d4967 Update README.md 2021-10-21 14:21:20 -05:00
Arthur Lu
49ee02d6fa Merge pull request #18 from titanscouting/daemon-fix
Fix messaging in daemon

Former-commit-id: 6a4d13a33f
2021-10-16 16:42:47 -07:00
Arthur Lu
08f5ba987a removed websockets from requirements.txr,
fixed return code of daemon,
removed websockets from hidden imports of superscript.spec


Former-commit-id: 828e45844e
2021-10-16 20:28:57 +00:00
Arthur Lu
dafd66447f moved sample zmq SUB client to test/
Former-commit-id: ab13e10271
2021-10-16 20:21:12 +00:00
Arthur Lu
6bcb3cbff4 verification of zmq solution working remotely
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 41fb81cfac
2021-10-15 06:20:05 +00:00
Arthur Lu
6cd092da37 solution using zmq PUB/SUB,
working locally


Former-commit-id: c0c46a1b9d
2021-10-15 06:12:50 +00:00
Arthur Lu
8540642bef works locally again
Former-commit-id: 7b05707e3b
2021-10-14 23:30:15 +00:00
Arthur Lu
5d0fbc06c6 possible fix: UDP broadcast,
not connecing from outside LAN

Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 531c8f80f3
2021-10-14 22:52:15 +00:00
Arthur Lu
a4a13c7cb5 set return value for profile option
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: e15f87b2e5
2021-10-14 19:45:28 +00:00
Arthur Lu
26d9d962c0 added close_all when exiting due to error
Former-commit-id: 9b614af85c
2021-10-13 22:32:42 +00:00
Arthur Lu
e20a212bd9 changes to stop() error reporting
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: bd77927421
2021-10-13 19:11:27 +00:00
Arthur Lu
1151541976 fixed key error in loop delay logic,
improved error logging to include stack trace

Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 3f32104c72
2021-10-12 22:16:34 +00:00
Arthur Lu
6f28e507a1 fixed errorlog path
Signed-off-by: Arthur Lu <learthurgo@gmail.com>

Former-commit-id: 0895eb3d74
2021-10-12 21:42:09 +00:00
Arthur Lu
1e6bc1926a fixed minor push_pit bug
Former-commit-id: 9603ca2be9
2021-10-11 02:59:49 +00:00
Arthur Lu
d89f997117 fixed sample config.json
Former-commit-id: 24e666a23b
2021-10-11 02:56:24 +00:00
Arthur Lu
31423d04d8 Merge pull request #17 from titanscouting/event-listener
Pull changes from event-listener to superscript-v1

Former-commit-id: 82b62924f6
2021-10-10 19:52:53 -07:00
Arthur Lu
44e9711b2d Merge branch 'superscript-v1' into event-listener
Former-commit-id: 3dbdcfbd35
2021-10-10 19:52:47 -07:00
Arthur Lu
f24d5163d7 Merge pull request #16 from titanscouting/database-config
Pull changes from database-config into superscript-v1

Former-commit-id: 790eb4aa03
2021-10-10 19:49:19 -07:00
Arthur Lu
06630b0dd4 Merge pull request #15 from titanscouting/automate-build
Update superscript-v1 with automate-build

Former-commit-id: 0fb586f13d
2021-10-10 19:47:48 -07:00
Arthur Lu
32ae4fd636 implemented event delay with dummy listener,
event delay listener in data.py unimplemented


Former-commit-id: dea5f3a374
2021-10-10 06:15:22 +00:00
Arthur Lu
96ebb82085 added opotion to pull config from database,
major code refactor


Former-commit-id: da913e639b
2021-09-23 07:10:01 +00:00
Arthur Lu
09b8cca884 Merge pull request #13 from titanscouting/superscript-v1
Pull recent changes from superscript-v1 to database-config

Former-commit-id: e18ddcec9d
2021-09-22 20:29:02 -07:00
Arthur Lu
fb1033e92c Merge branch 'databse-config' into superscript-v1
Former-commit-id: a64c2c71ca
2021-09-22 20:28:55 -07:00
Arthur Lu
16882a0a75 added debug option to usage description,
set generic error code to 1


Former-commit-id: 9163244e2c
2021-09-21 23:36:13 +00:00
Arthur Lu
2b8ecc5bee added databse config getter/setter to data.py,
fixed args for data.py functions


Former-commit-id: 74bcc116a2
2021-09-21 05:14:54 +00:00
Arthur Lu
8112effbce added debug option,
improved memory usage slightly,
changed errorlog.txt to errorlog.log,
updated .gitignore


Former-commit-id: bd51efc6c2
2021-09-21 04:43:32 +00:00
Arthur Lu
56d3a0adcd added event and time delay options
(event delay unimplemented)


Former-commit-id: fb4e5da1d4
2021-08-27 23:39:48 +00:00
Arthur Lu
d56411253c fixed badge url 2021-08-26 18:20:11 -07:00
Arthur Lu
c415225afe Update release badge 2021-08-26 18:11:25 -07:00
Arthur Lu
2444963af9 changed asset upload name
removed create criteria, must be publish


Former-commit-id: 73b5c393a0
2021-08-26 23:19:53 +00:00
Arthur Lu
8000a7314d add release asset automaticallt
Former-commit-id: 42ca74b4ab
2021-08-26 23:14:09 +00:00
Arthur Lu
3e212e4502 fixed typo
Former-commit-id: fc63d5d7e1
2021-08-26 22:57:15 +00:00
Arthur Lu
66e00987c4 fixed path
Former-commit-id: 1106a0ffb1
2021-08-26 22:53:21 +00:00
Arthur Lu
2f90e7d11a added prerequisite and build steps
Former-commit-id: 65a1720657
2021-08-26 22:48:48 +00:00
Arthur Lu
f0ef4fea5d Merge pull request #12 from titanscouting/superscript-v1
Merge current changes to build-superscript

Former-commit-id: 6b4de40c49
2021-08-26 15:45:24 -07:00
Arthur Lu
9be9008ae1 fixed and properly named build action
Former-commit-id: 694733700a
2021-08-26 22:26:29 +00:00
Arthur Lu
097fd2836b reorganized imports in superscript
Former-commit-id: 18c26a00b6
2021-08-22 05:35:04 +00:00
Arthur Lu
052788afb9 fixed verbose/profile output options
Former-commit-id: ca399cf350
2021-08-19 20:58:35 +00:00
Arthur Lu
e4eb824f51 Merge pull request #11 from titanscouting/daemonize-superscript
Merge changes in daemonize-superscript to refactor-superscript

Former-commit-id: 3e8d876f80
2021-08-18 17:36:55 -07:00
Arthur Lu
11d3db4b44 added profile option to superscript
Former-commit-id: ea07d7c709
2021-08-19 00:34:42 +00:00
Arthur Lu
76f78047b3 unified main_lin, main_win functions
Former-commit-id: 342dae3022
2021-08-18 22:35:42 +00:00
Arthur Lu
20f2040a1a changed websocket bind address to 0.0.0.0
Former-commit-id: e9258c831d
2021-08-18 05:58:21 +00:00
Arthur Lu
ffead9e240 fixed daemon no start issue
Former-commit-id: efc353dafb
2021-08-18 05:13:25 +00:00
Arthur Lu
0287b5c0e2 temporary workaround for missing ssl cert
Former-commit-id: 739a2f36f8
2021-08-18 03:26:47 +00:00
Arthur Lu
b6a1dfedb9 not working
Former-commit-id: e82177d17b
2021-08-18 03:04:01 +00:00
Arthur Lu
cafb773d8b replaced profile to verbose option
Former-commit-id: 055c296c00
2021-08-18 00:43:00 +00:00
Arthur Lu
871b313d95 fixed linux only import in windows exec
Former-commit-id: 61ae377e97
2021-08-17 14:17:40 -07:00
Arthur Lu
bcbb653696 daemonized, socketed superscript
improved runtime
removed superscript-socket.py


Former-commit-id: 6fa29f767d
2021-08-17 21:02:08 +00:00
Arthur Lu
b4c7365bf0 added *.pid files to git ignore
Former-commit-id: f8f8d6bf27
2021-08-13 23:32:59 +00:00
Arthur Lu
c2f35f4cb2 superscript v 0.9.2
Former-commit-id: e559ced751
2021-08-13 21:57:03 +00:00
Arthur Lu
2ebd2cba8a removed socket/daemon test scripts
Former-commit-id: d1a9e56703
2021-08-12 22:26:37 +00:00
Arthur Lu
6819aaf143 consolidated dataset/data imports
Former-commit-id: 6364746d7a
2021-08-12 21:58:41 +00:00
Arthur Lu
b3ab9156db consolidated datraset.py into datas.py
removed unessasary time import in data.py
added missing import to processing.py


Former-commit-id: f74cfb3ae3
2021-08-12 21:53:03 +00:00
Arthur Lu
30641e43d8 fixed delay in daemon stopping
Former-commit-id: 1d9fa99058
2021-08-11 23:37:57 +00:00
Arthur Lu
3a068654ed added start/stop/restart argument functionality
slightly buggy


Former-commit-id: ba793140af
2021-08-11 23:26:52 +00:00
Arthur Lu
962061007b removed time-test
Former-commit-id: c09f4d0897
2021-08-11 22:54:24 +00:00
Arthur Lu
91f34a8d74 daemonized superscript socket example
added python-daemon to requirements.txt


Former-commit-id: 922095ebe0
2021-08-11 22:28:24 +00:00
Arthur Lu
19bca6967c added websockets to requirements.txt
Former-commit-id: d9ba7bcb24
2021-08-11 18:21:34 +00:00
Arthur Lu
fb2ea60fea started socketing superscript statuses
Former-commit-id: a703fe4867
2021-08-11 18:10:04 +00:00
Arthur Lu
5d95913467 removed duplicate requirements
Former-commit-id: f258a768be
2021-08-11 00:33:06 +00:00
Arthur Lu
7e800c9004 added Pool.join to allow threads to exit safely
added keyboard interrupt signal ignore in threads


Former-commit-id: 836e9ca6be
2021-07-16 06:12:26 +00:00
Arthur Lu
3c7262498c superscript v 0.9.1
Former-commit-id: 246efd524b
2021-06-13 00:49:04 +00:00
Arthur Lu
4c65e88903 finished refactor
Former-commit-id: b2f2dfe2a4
2021-06-12 23:57:16 +00:00
Arthur Lu
b3c26ce2cf renamed cli_interface.py to interface.py
Former-commit-id: b94c9125b3
2021-06-12 07:16:11 +00:00
Arthur Lu
089ff7ec01 separated gui and cli dev files
began refactoring superscript in cli application


Former-commit-id: ee309b9f8b
2021-06-12 07:09:26 +00:00
Arthur Lu
d684813ee0 Merge pull request #10 from titanscouting/automate-build
Automate build
2021-06-09 14:58:21 -07:00
Arthur Lu
26079f3180 fixed pathing for build-CLI.*
added temp directory to gitignore
2021-04-27 07:26:14 +00:00
Arthur Lu
99e722c400 removed ThreadPoolExecutor import 2021-04-25 06:05:33 +00:00
Arthur Lu
f5a0e0fe8c added sample build-cli workflow 2021-04-25 03:51:01 +00:00
Arthur Lu
28e423942f added .gitattributes 2021-04-15 19:41:10 +00:00
Arthur Lu
8977f8c277 added compiled binaries with no file endings
to gitignore
2021-04-13 04:05:46 +00:00
Arthur Lu
2b0f718aa5 removed compiled binaries
added compiled binaries in /dist/ to gitignore
2021-04-13 04:03:07 +00:00
Arthur Lu
30469a3211 removed matplotlib import
removed plotting pit analysis
fixed warning supression for win exe
superscript v 0.8.6
2021-04-12 15:13:54 -07:00
Arthur Lu
391d4e1996 created batch script for windows compilation 2021-04-12 14:39:00 -07:00
Arthur Lu
224f64e8b7 better fix for devcontainer.json 2021-04-12 06:30:21 +00:00
Arthur Lu
aa7d7ca927 quick patch for devcontainer.json 2021-04-12 06:27:50 +00:00
Arthur Lu
d10c16d483 superscript v 0.8.5 2021-04-10 06:08:18 +00:00
Arthur Lu
f211d00f2d superscript v 0.8.4 2021-04-09 23:45:16 +00:00
Arthur Lu
69c707689b superscript v 0.8.3 2021-04-03 20:47:45 +00:00
Arthur Lu
d2f9c802b3 built and verified threading fixes 2021-04-02 22:04:06 +00:00
Arthur Lu
99e28f5e83 fixed .gitignore
added build-CLI script
fixed threading in superscript
2021-04-02 21:58:35 +00:00
Arthur Lu
18dbc174bd deleted config.json
changed superscript config lookup to relative path
added additional requirements to requirements.txt
added build spec file for superscript
2021-04-02 21:35:05 +00:00
Arthur Lu
79689d69c8 fixed spelling in default config,
added config to git ignore
2021-04-02 01:28:25 +00:00
Dev Singh
80c3f1224b Merge pull request #3 from titanscouting/superscript-main
Merge initial changes
2021-04-01 13:40:29 -05:00
Dev Singh
960a1b3165 fix ut and file structure 2021-04-01 13:38:53 -05:00
Arthur Lu
89fcd366d3 Merge branch 'master' into superscript-main 2021-04-01 11:34:44 -07:00
Dev Singh
79cde44108 Create SECURITY.md 2021-04-01 13:11:38 -05:00
Dev Singh
2b896db9a9 Create MAINTAINERS 2021-04-01 13:11:22 -05:00
Dev Singh
483897c011 Merge pull request #1 from titanscouting/add-license-1
Create LICENSE
2021-04-01 13:11:03 -05:00
Dev Singh
9287d98fe2 Create LICENSE 2021-04-01 13:10:50 -05:00
Dev Singh
991751a340 Create CONTRIBUTING.md 2021-04-01 13:10:14 -05:00
Dev Singh
9d2476b5eb Create README.md 2021-04-01 13:09:18 -05:00
21 changed files with 1547 additions and 411 deletions

View File

@@ -8,16 +8,10 @@
"python.pythonPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
"python.testing.pytestPath": "/usr/local/py-utils/bin/pytest"
"python.linting.pylintPath": "/usr/local/bin/pylint",
"python.testing.pytestPath": "/usr/local/bin/pytest",
"editor.tabSize": 4,
"editor.insertSpaces": false
},
"extensions": [
"mhutchie.git-graph",

View File

@@ -0,0 +1,16 @@
cerberus
dnspython
numpy
pandas
pyinstaller
pylint
pymongo
pyparsing
pytest
python-daemon
pyzmq
requests
scikit-learn
scipy
six
tra-analysis

View File

@@ -1,38 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

10
.gitignore vendored
View File

@@ -12,3 +12,13 @@
**/errorlog.txt
/dist/superscript.*
/dist/superscript
**/*.pid
**/profile.*
**/*.log
**/errorlog.txt
/dist/*
slurm-tra-superscript.out
config*.json

View File

@@ -1,4 +1,4 @@
# Red Alliance Analysis &middot; ![GitHub release (latest by date)](https://img.shields.io/github/v/release/titanscout2022/red-alliance-analysis)
# Red Alliance Analysis &middot; ![GitHub release (latest by date)](https://img.shields.io/github/v/release/titanscouting/tra-superscript)
Titan Robotics 2022 Strategy Team Repository for Data Analysis Tools. Included with these tools are the backend data analysis engine formatted as a python package, associated binaries for the analysis package, and premade scripts that can be pulled directly from this repository and will integrate with other Red Alliance applications to quickly deploy FRC scouting tools.

251
competition/config.py Normal file
View File

@@ -0,0 +1,251 @@
import json
from exceptions import ConfigurationError
from cerberus import Validator
from data import set_database_config, get_database_config
class Configuration:
path = None
config = {}
_sample_config = {
"persistent":{
"key":{
"database":"",
"tba":"",
"tra":{
"CLIENT_ID":"",
"CLIENT_SECRET":"",
"url": ""
}
},
"config-preference":"local",
"synchronize-config":False
},
"variable":{
"event-delay":False,
"loop-delay":0,
"competition": "2020ilch",
"modules":{
"match":{
"tests":{
"balls-blocked":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-collected":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-lower-teleop":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-lower-auto":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-started":[
"basic_stats",
"historical_analyss",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-upper-teleop":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-upper-auto":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
]
}
},
"metric":{
"tests":{
"elo":{
"score":1500,
"N":400,
"K":24
},
"gl2":{
"score":1500,
"rd":250,
"vol":0.06
},
"ts":{
"mu":25,
"sigma":8.33
}
}
},
"pit":{
"tests":{
"wheel-mechanism":True,
"low-balls":True,
"high-balls":True,
"wheel-success":True,
"strategic-focus":True,
"climb-mechanism":True,
"attitude":True
}
}
}
}
}
_validation_schema = {
"persistent": {
"type": "dict",
"required": True,
"require_all": True,
"schema": {
"key": {
"type": "dict",
"require_all":True,
"schema": {
"database": {"type":"string"},
"tba": {"type": "string"},
"tra": {
"type": "dict",
"require_all": True,
"schema": {
"CLIENT_ID": {"type": "string"},
"CLIENT_SECRET": {"type": "string"},
"url": {"type": "string"}
}
}
}
},
"config-preference": {"type": "string", "required": True},
"synchronize-config": {"type": "boolean", "required": True}
}
}
}
def __init__(self, path):
self.path = path
self.load_config()
self.validate_config()
def load_config(self):
try:
f = open(self.path, "r")
self.config.update(json.load(f))
f.close()
except:
self.config = self._sample_config
self.save_config()
f.close()
raise ConfigurationError("could not find config file at <" + self.path + ">, created new sample config file at that path")
def save_config(self):
f = open(self.path, "w+")
json.dump(self.config, f, ensure_ascii=False, indent=4)
f.close()
def validate_config(self):
v = Validator(self._validation_schema, allow_unknown = True)
isValidated = v.validate(self.config)
if not isValidated:
raise ConfigurationError("config validation error: " + v.errors)
def __getattr__(self, name): # simple linear lookup method for common multikey-value paths, TYPE UNSAFE
if name == "persistent":
return self.config["persistent"]
elif name == "key":
return self.config["persistent"]["key"]
elif name == "database":
# soon to be deprecated
return self.config["persistent"]["key"]["database"]
elif name == "tba":
return self.config["persistent"]["key"]["tba"]
elif name == "tra":
return self.config["persistent"]["key"]["tra"]
elif name == "priority":
return self.config["persistent"]["config-preference"]
elif name == "sync":
return self.config["persistent"]["synchronize-config"]
elif name == "variable":
return self.config["variable"]
elif name == "event_delay":
return self.config["variable"]["event-delay"]
elif name == "loop_delay":
return self.config["variable"]["loop-delay"]
elif name == "competition":
return self.config["variable"]["competition"]
elif name == "modules":
return self.config["variable"]["modules"]
else:
return None
def __getitem__(self, key):
return self.config[key]
def resolve_config_conflicts(self, logger, client): # needs improvement with new localization scheme
sync = self.sync
priority = self.priority
if sync:
if priority == "local" or priority == "client":
logger.info("config-preference set to local/client, loading local config information")
remote_config = get_database_config(client)
if remote_config != self.config["variable"]:
set_database_config(client, self.config["variable"])
logger.info("database config was different and was updated")
# no change to config
elif priority == "remote" or priority == "database":
logger.info("config-preference set to remote/database, loading remote config information")
remote_config = get_database_config(client)
if remote_config != self.config["variable"]:
self.config["variable"] = remote_config
self.save_config()
# change variable to match remote
logger.info("local config was different and was updated")
else:
raise ConfigurationError("persistent/config-preference field must be \"local\"/\"client\" or \"remote\"/\"database\"")
else:
if priority == "local" or priority == "client":
logger.info("config-preference set to local/client, loading local config information")
# no change to config
elif priority == "remote" or priority == "database":
logger.info("config-preference set to remote/database, loading database config information")
self.config["variable"] = get_database_config(client)
# change variable to match remote without updating local version
else:
raise ConfigurationError("persistent/config-preference field must be \"local\"/\"client\" or \"remote\"/\"database\"")

218
competition/data.py Normal file
View File

@@ -0,0 +1,218 @@
from calendar import c
import requests
import pull
import pandas as pd
import json
def pull_new_tba_matches(apikey, competition, last_match):
api_key= apikey
x=requests.get("https://www.thebluealliance.com/api/v3/event/"+competition+"/matches/simple", headers={"X-TBA-Auth-Key":api_key})
json = x.json()
out = []
for i in json:
if i["actual_time"] != None and i["comp_level"] == "qm" and i["match_number"] > last_match :
out.append({"match" : i['match_number'], "blue" : list(map(lambda x: int(x[3:]), i['alliances']['blue']['team_keys'])), "red" : list(map(lambda x: int(x[3:]), i['alliances']['red']['team_keys'])), "winner": i["winning_alliance"]})
out.sort(key=lambda x: x['match'])
return out
def pull_new_tba_matches_manual(apikey, competition, cutoff):
filename = competition+"-wins.json"
with open(filename, 'r') as f:
data = json.load(f)
return data
def get_team_match_data(client, competition, team_num):
db = client.data_scouting
mdata = db.matchdata
out = {}
for i in mdata.find({"competition" : competition, "team_scouted": str(team_num)}):
out[i['match']] = i['data']
return pd.DataFrame(out)
def clear_metrics(client, competition):
db = client.data_processing
data = db.team_metrics
data.delete_many({competition: competition})
return True
def get_team_pit_data(client, competition, team_num):
db = client.data_scouting
mdata = db.pitdata
out = {}
return mdata.find_one({"competition" : competition, "team_scouted": str(team_num)})["data"]
def get_team_metrics_data(client, competition, team_num):
db = client.data_processing
mdata = db.team_metrics
temp = mdata.find_one({"team": team_num})
if temp != None:
if competition in temp['metrics'].keys():
temp = temp['metrics'][competition]
else :
temp = None
else:
temp = None
return temp
def get_match_data_formatted(client, competition):
teams_at_comp = pull.get_teams_at_competition(competition)
out = {}
for team in teams_at_comp:
try:
out[int(team)] = unkeyify_2l(get_team_match_data(client, competition, team).transpose().to_dict())
except:
pass
return out
def get_metrics_data_formatted(client, competition):
teams_at_comp = pull.get_teams_at_competition(competition)
out = {}
for team in teams_at_comp:
try:
out[int(team)] = get_team_metrics_data(client, competition, int(team))
except:
pass
return out
def get_pit_data_formatted(client, competition):
x=requests.get("https://scouting.titanrobotics2022.com/api/fetchAllTeamNicknamesAtCompetition?competition="+competition)
x = x.json()
x = x['data']
x = x.keys()
out = {}
for i in x:
try:
out[int(i)] = get_team_pit_data(client, competition, int(i))
except:
pass
return out
def get_pit_variable_data(client, competition):
db = client.data_processing
mdata = db.team_pit
out = {}
return mdata.find()
def get_pit_variable_formatted(client, competition):
temp = get_pit_variable_data(client, competition)
out = {}
for i in temp:
out[i["variable"]] = i["data"]
return out
def push_team_tests_data(client, competition, team_num, data, dbname = "data_processing", colname = "team_tests"):
db = client[dbname]
mdata = db[colname]
mdata.replace_one({"competition" : competition, "team": team_num}, {"_id": competition+str(team_num)+"am", "competition" : competition, "team" : team_num, "data" : data}, True)
def push_team_metrics_data(client, competition, team_num, data, dbname = "data_processing", colname = "team_metrics"):
db = client[dbname]
mdata = db[colname]
mdata.update_one({"team": team_num}, {"$set": {"metrics.{}".format(competition): data}}, upsert=True)
def push_team_pit_data(client, competition, variable, data, dbname = "data_processing", colname = "team_pit"):
db = client[dbname]
mdata = db[colname]
mdata.replace_one({"competition" : competition, "variable": variable}, {"competition" : competition, "variable" : variable, "data" : data}, True)
def get_analysis_flags(client, flag):
db = client.data_processing
mdata = db.flags
return mdata.find_one({"_id": "2022"})
def set_analysis_flags(client, flag, data):
db = client.data_processing
mdata = db.flags
return mdata.update_one({"_id": "2022"}, {"$set": data})
def unkeyify_2l(layered_dict):
out = {}
for i in layered_dict.keys():
add = []
sortkey = []
for j in layered_dict[i].keys():
add.append([j,layered_dict[i][j]])
add.sort(key = lambda x: x[0])
out[i] = list(map(lambda x: x[1], add))
return out
def get_previous_time(client):
previous_time = get_analysis_flags(client, "latest_update")
if previous_time == None:
set_analysis_flags(client, "latest_update", 0)
previous_time = 0
else:
previous_time = previous_time["latest_update"]
return previous_time
def set_current_time(client, current_time):
set_analysis_flags(client, "latest_update", {"latest_update":current_time})
def get_database_config(client):
remote_config = get_analysis_flags(client, "config")
return remote_config["config"] if remote_config != None else None
def set_database_config(client, config):
set_analysis_flags(client, "config", {"config": config})
def load_match(client, competition):
return get_match_data_formatted(client, competition)
def load_metric(client, competition, match, group_name, metrics):
group = {}
for team in match[group_name]:
db_data = get_team_metrics_data(client, competition, team)
if db_data == None:
gl2 = {"score": metrics["gl2"]["score"], "rd": metrics["gl2"]["rd"], "vol": metrics["gl2"]["vol"]}
group[team] = {"gl2": gl2}
else:
metrics = db_data
gl2 = metrics["gl2"]
group[team] = {"gl2": gl2}
return group
def load_pit(client, competition):
return get_pit_data_formatted(client, competition)
def push_match(client, competition, results):
for team in results:
push_team_tests_data(client, competition, team, results[team])
def push_metric(client, competition, metric):
for team in metric:
push_team_metrics_data(client, competition, team, metric[team])
def push_pit(client, competition, pit):
for variable in pit:
push_team_pit_data(client, competition, variable, pit[variable])
def check_new_database_matches(client, competition):
return True

132
competition/dep.py Normal file
View File

@@ -0,0 +1,132 @@
# contains deprecated functions, not to be used unless nessasary!
import json
sample_json = """
{
"persistent":{
"key":{
"database":"",
"tba":"",
"tra":{
"CLIENT_ID":"",
"CLIENT_SECRET":"",
"url": ""
}
},
"config-preference":"local",
"synchronize-config":false
},
"variable":{
"max-threads":0.5,
"team":"",
"event-delay":false,
"loop-delay":0,
"reportable":true,
"teams":[
],
"modules":{
"match":{
"tests":{
"balls-blocked":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-collected":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-lower-teleop":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-lower-auto":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-started":[
"basic_stats",
"historical_analyss",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-upper-teleop":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
],
"balls-upper-auto":[
"basic_stats",
"historical_analysis",
"regression_linear",
"regression_logarithmic",
"regression_exponential",
"regression_polynomial",
"regression_sigmoidal"
]
}
},
"metric":{
"tests":{
"gl2":{
"score":1500,
"rd":250,
"vol":0.06
},
}
},
"pit":{
"tests":{
"wheel-mechanism":true,
"low-balls":true,
"high-balls":true,
"wheel-success":true,
"strategic-focus":true,
"climb-mechanism":true,
"attitude":true
}
}
}
}
}
"""
def load_config(path, config_vector):
try:
f = open(path, "r")
config_vector.update(json.load(f))
f.close()
return 0
except:
f = open(path, "w")
f.write(sample_json)
f.close()
return 1

View File

@@ -0,0 +1,7 @@
class APIError(Exception):
def __init__(self, str):
super().__init__(str)
class ConfigurationError (Exception):
def __init__(self, str):
super().__init__(str)

91
competition/interface.py Normal file
View File

@@ -0,0 +1,91 @@
from logging import Logger as L
import datetime
import platform
import json
class Logger(L):
file = None
levels = {
0: "",
10:"[DEBUG] ",
20:"[INFO] ",
30:"[WARNING] ",
40:"[ERROR] ",
50:"[CRITICAL]",
}
targets = []
def __init__(self, verbose, profile, debug, file = None):
super().__init__("tra_logger")
self.file = file
if file != None:
self.targets.append(self._send_file)
if profile:
self.targets.append(self._send_null)
elif verbose:
self.targets.append(self._send_scli)
elif debug:
self.targets.append(self._send_scli)
else:
self.targets.append(self._send_null)
def _send_null(self, msg):
pass
def _send_scli(self, msg):
print(msg)
def _send_file(self, msg):
f = open(self.file, 'a')
f.write(msg + "\n")
f.close()
def get_time_formatted(self):
return datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S %Z")
def log(self, level, msg):
for t in self.targets:
t(self.get_time_formatted() + "| " + self.levels[level] + ": " + msg)
def debug(self, msg):
self.log(10, msg)
def info(self, msg):
self.log(20, msg)
def warning(self, msg):
self.log(30, msg)
def error(self, msg):
self.log(40, msg)
def critical(self, msg):
self.log(50, msg)
def splash(self, version):
def hrule():
self.log(0, "#"+38*"-"+"#")
def box(s):
temp = "|"
temp += s
temp += (40-len(s)-2)*" "
temp += "|"
self.log(0, temp)
hrule()
box(" superscript version: " + version)
box(" os: " + platform.system())
box(" python: " + platform.python_version())
hrule()
def save_module_to_file(self, module, data, results):
f = open(module + ".log", "w")
json.dump({"data": data, "results":results}, f, ensure_ascii=False, indent=4)
f.close()

309
competition/module.py Normal file
View File

@@ -0,0 +1,309 @@
import abc
import data as d
import signal
import numpy as np
from tra_analysis import Analysis as an
from tqdm import tqdm
class Module(metaclass = abc.ABCMeta):
@classmethod
def __subclasshook__(cls, subclass):
return (hasattr(subclass, '__init__') and
callable(subclass.__init__) and
hasattr(subclass, 'validate_config') and
callable(subclass.validate_config) and
hasattr(subclass, 'run') and
callable(subclass.run)
)
@abc.abstractmethod
def __init__(self, config, apikey, tbakey, timestamp, competition, *args, **kwargs):
raise NotImplementedError
@abc.abstractmethod
def validate_config(self, *args, **kwargs):
raise NotImplementedError
@abc.abstractmethod
def run(self, *args, **kwargs):
raise NotImplementedError
class Match (Module):
config = None
apikey = None
tbakey = None
timestamp = None
competition = None
data = None
results = None
def __init__(self, config, apikey, tbakey, timestamp, competition):
self.config = config
self.apikey = apikey
self.tbakey = tbakey
self.timestamp = timestamp
self.competition = competition
def validate_config(self):
return True, ""
def run(self):
self._load_data()
self._process_data()
self._push_results()
def _load_data(self):
self.data = d.load_match(self.apikey, self.competition)
def _simplestats(self, data_test):
signal.signal(signal.SIGINT, signal.SIG_IGN)
data = np.array(data_test[3])
data = data[np.isfinite(data)]
ranges = list(range(len(data)))
test = data_test[2]
if test == "basic_stats":
return an.basic_stats(data)
if test == "historical_analysis":
return an.histo_analysis([ranges, data])
if test == "regression_linear":
return an.regression(ranges, data, ['lin'])
if test == "regression_logarithmic":
return an.regression(ranges, data, ['log'])
if test == "regression_exponential":
return an.regression(ranges, data, ['exp'])
if test == "regression_polynomial":
return an.regression(ranges, data, ['ply'])
if test == "regression_sigmoidal":
return an.regression(ranges, data, ['sig'])
def _process_data(self):
tests = self.config["tests"]
data = self.data
input_vector = []
for team in data:
for variable in data[team]:
if variable in tests:
for test in tests[variable]:
input_vector.append((team, variable, test, data[team][variable]))
self.data = input_vector
self.results = []
for test_var_data in self.data:
self.results.append(self._simplestats(test_var_data))
def _push_results(self):
short_mapping = {"regression_linear": "lin", "regression_logarithmic": "log", "regression_exponential": "exp", "regression_polynomial": "ply", "regression_sigmoidal": "sig"}
class AutoVivification(dict):
def __getitem__(self, item):
try:
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
return value
result_filtered = self.results
input_vector = self.data
return_vector = AutoVivification()
i = 0
for result in result_filtered:
filtered = input_vector[i][2]
try:
short = short_mapping[filtered]
return_vector[input_vector[i][0]][input_vector[i][1]][input_vector[i][2]] = result[short]
except KeyError: # not in mapping
return_vector[input_vector[i][0]][input_vector[i][1]][input_vector[i][2]] = result
i += 1
self.results = return_vector
d.push_match(self.apikey, self.competition, self.results)
class Metric (Module):
config = None
apikey = None
tbakey = None
timestamp = None
competition = None
data = None
results = None
def __init__(self, config, apikey, tbakey, timestamp, competition):
self.config = config
self.apikey = apikey
self.tbakey = tbakey
self.timestamp = timestamp
self.competition = competition
def validate_config(self):
return True, ""
def run(self):
self._load_data()
self._process_data()
self._push_results()
def _load_data(self):
self.last_match = d.get_analysis_flags(self.apikey, 'metrics_last_match')['metrics_last_match']
print("Previous last match", self.last_match)
self.data = d.pull_new_tba_matches(self.tbakey, self.competition, self.last_match)
def _process_data(self):
self.results = {}
self.match = self.last_match
matches = self.data
red = {}
blu = {}
for match in tqdm(matches, desc="Metrics"): # grab matches and loop through each one
self.match = max(self.match, int(match['match']))
red = d.load_metric(self.apikey, self.competition, match, "red", self.config["tests"]) # get the current ratings for red
blu = d.load_metric(self.apikey, self.competition, match, "blue", self.config["tests"]) # get the current ratings for blue
gl2_red_score_total = 0
gl2_blu_score_total = 0
gl2_red_rd_total = 0
gl2_blu_rd_total = 0
gl2_red_vol_total = 0
gl2_blu_vol_total = 0
for team in red: # for each team in red, add up gl2 score components
gl2_red_score_total += red[team]["gl2"]["score"]
gl2_red_rd_total += red[team]["gl2"]["rd"]
gl2_red_vol_total += red[team]["gl2"]["vol"]
for team in blu: # for each team in blue, add up gl2 score components
gl2_blu_score_total += blu[team]["gl2"]["score"]
gl2_blu_rd_total += blu[team]["gl2"]["rd"]
gl2_blu_vol_total += blu[team]["gl2"]["vol"]
red_gl2 = {"score": gl2_red_score_total / len(red), "rd": gl2_red_rd_total / len(red), "vol": gl2_red_vol_total / len(red)} # average the scores by dividing by 3
blu_gl2 = {"score": gl2_blu_score_total / len(blu), "rd": gl2_blu_rd_total / len(blu), "vol": gl2_blu_vol_total / len(blu)} # average the scores by dividing by 3
if match["winner"] == "red": # if red won, set observations to {"red": 1, "blu": 0}
observations = {"red": 1, "blu": 0}
elif match["winner"] == "blue": # if blue won, set observations to {"red": 0, "blu": 1}
observations = {"red": 0, "blu": 1}
else: # otherwise it was a tie and observations is {"red": 0.5, "blu": 0.5}
observations = {"red": 0.5, "blu": 0.5}
new_red_gl2_score, new_red_gl2_rd, new_red_gl2_vol = an.Metric().glicko2(red_gl2["score"], red_gl2["rd"], red_gl2["vol"], [blu_gl2["score"]], [blu_gl2["rd"]], [observations["red"], observations["blu"]]) # calculate new scores for gl2 for red
new_blu_gl2_score, new_blu_gl2_rd, new_blu_gl2_vol = an.Metric().glicko2(blu_gl2["score"], blu_gl2["rd"], blu_gl2["vol"], [red_gl2["score"]], [red_gl2["rd"]], [observations["blu"], observations["red"]]) # calculate new scores for gl2 for blue
red_gl2_delta = {"score": new_red_gl2_score - red_gl2["score"], "rd": new_red_gl2_rd - red_gl2["rd"], "vol": new_red_gl2_vol - red_gl2["vol"]} # calculate gl2 deltas for red
blu_gl2_delta = {"score": new_blu_gl2_score - blu_gl2["score"], "rd": new_blu_gl2_rd - blu_gl2["rd"], "vol": new_blu_gl2_vol - blu_gl2["vol"]} # calculate gl2 deltas for blue
for team in red: # for each team on red, add the previous score with the delta to find the new score
red[team]["gl2"]["score"] = red[team]["gl2"]["score"] + red_gl2_delta["score"]
red[team]["gl2"]["rd"] = red[team]["gl2"]["rd"] + red_gl2_delta["rd"]
red[team]["gl2"]["vol"] = red[team]["gl2"]["vol"] + red_gl2_delta["vol"]
for team in blu: # for each team on blue, add the previous score with the delta to find the new score
blu[team]["gl2"]["score"] = blu[team]["gl2"]["score"] + blu_gl2_delta["score"]
blu[team]["gl2"]["rd"] = blu[team]["gl2"]["rd"] + blu_gl2_delta["rd"]
blu[team]["gl2"]["vol"] = blu[team]["gl2"]["vol"] + blu_gl2_delta["vol"]
temp_vector = {}
temp_vector.update(red) # update the team's score with the temporay vector
temp_vector.update(blu)
self.results[match['match']] = temp_vector
d.push_metric(self.apikey, self.competition, temp_vector) # push new scores to db
print("New last match", self.match)
d.set_analysis_flags(self.apikey, 'metrics_last_match', {'metrics_last_match': self.match})
def _push_results(self):
pass
class Pit (Module):
config = None
apikey = None
tbakey = None
timestamp = None
competition = None
data = None
results = None
def __init__(self, config, apikey, tbakey, timestamp, competition):
self.config = config
self.apikey = apikey
self.tbakey = tbakey
self.timestamp = timestamp
self.competition = competition
def validate_config(self):
return True, ""
def run(self):
self._load_data()
self._process_data()
self._push_results()
def _load_data(self):
self.data = d.load_pit(self.apikey, self.competition)
def _process_data(self):
tests = self.config["tests"]
return_vector = {}
for team in self.data:
for variable in self.data[team]:
if variable in tests:
if not variable in return_vector:
return_vector[variable] = []
return_vector[variable].append(self.data[team][variable])
self.results = return_vector
def _push_results(self):
d.push_pit(self.apikey, self.competition, self.results)
class Rating (Module):
pass
class Heatmap (Module):
pass
class Sentiment (Module):
pass

63
competition/pull.py Normal file
View File

@@ -0,0 +1,63 @@
import requests
from exceptions import APIError
from dep import load_config
url = "https://scouting.titanrobotics2022.com"
config_tra = {}
load_config("config.json", config_tra)
trakey = config_tra['persistent']['key']['tra']
def get_team_competition():
endpoint = '/api/fetchTeamCompetition'
params = {
"CLIENT_ID": trakey['CLIENT_ID'],
"CLIENT_SECRET": trakey['CLIENT_SECRET']
}
response = requests.request("GET", url + endpoint, params=params)
json = response.json()
if json['success']:
return json['competition']
else:
raise APIError(json)
def get_team():
endpoint = '/api/fetchTeamCompetition'
params = {
"CLIENT_ID": trakey['CLIENT_ID'],
"CLIENT_SECRET": trakey['CLIENT_SECRET']
}
response = requests.request("GET", url + endpoint, params=params)
json = response.json()
if json['success']:
return json['team']
else:
raise APIError(json)
def get_team_match_data(competition, team_num):
endpoint = '/api/fetchAllTeamMatchData'
params = {
"competition": competition,
"teamScouted": team_num,
"CLIENT_ID": trakey['CLIENT_ID'],
"CLIENT_SECRET": trakey['CLIENT_SECRET']
}
response = requests.request("GET", url + endpoint, params=params)
json = response.json()
if json['success']:
return json['data'][team_num]
else:
raise APIError(json)
def get_teams_at_competition(competition):
endpoint = '/api/fetchAllTeamNicknamesAtCompetition'
params = {
"competition": competition,
"CLIENT_ID": trakey['CLIENT_ID'],
"CLIENT_SECRET": trakey['CLIENT_SECRET']
}
response = requests.request("GET", url + endpoint, params=params)
json = response.json()
if json['success']:
return list(json['data'].keys())
else:
raise APIError(json)

View File

@@ -0,0 +1,15 @@
cerberus
dnspython
numpy
pandas
pyinstaller
pylint
pymongo
pyparsing
python-daemon
pyzmq
requests
scikit-learn
scipy
six
tra-analysis

402
competition/superscript.py Normal file
View File

@@ -0,0 +1,402 @@
# Titan Robotics Team 2022: Superscript Script
# Written by Arthur Lu, Jacob Levine, and Dev Singh
# Notes:
# setup:
__version__ = "1.0.0"
# changelog should be viewed using print(analysis.__changelog__)
__changelog__ = """changelog:
1.0.0:
- superscript now runs in PEP 3143 compliant well behaved daemon on Linux systems
- linux superscript daemon has integrated websocket output to monitor progress/status remotely
- linux daemon now sends stderr to errorlog.log
- added verbose option to linux superscript to allow for interactive output
- moved pymongo import to superscript.py
- added profile option to linux superscript to profile runtime of script
- reduced memory usage slightly by consolidating the unwrapped input data
- added debug option, which performs one loop of analysis and dumps results to local files
- added event and time delay options to config
- event delay pauses loop until even listener recieves an update
- time delay pauses loop until the time specified has elapsed since the BEGINNING of previous loop
- added options to pull config information from database (reatins option to use local config file)
- config-preference option selects between prioritizing local config and prioritizing database config
- synchronize-config option selects whether to update the non prioritized config with the prioritized one
- divided config options between persistent ones (keys), and variable ones (everything else)
- generalized behavior of various core components by collecting loose functions in several dependencies into classes
- module.py contains classes, each one represents a single data analysis routine
- config.py contains the Configuration class, which stores the configuration information and abstracts the getter methods
0.9.3:
- improved data loading performance by removing redundant PyMongo client creation (120s to 14s)
- passed singular instance of PyMongo client as standin for apikey parameter in all data.py functions
0.9.2:
- removed unessasary imports from data
- minor changes to interface
0.9.1:
- fixed bugs in configuration item loading exception handling
0.9.0:
- moved printing and logging related functions to interface.py (changelog will stay in this file)
- changed function return files for load_config and save_config to standard C values (0 for success, 1 for error)
- added local variables for config location
- moved dataset getting and setting functions to dataset.py (changelog will stay in this file)
- moved matchloop, metricloop, pitloop and helper functions (simplestats) to processing.py
0.8.6:
- added proper main function
0.8.5:
- added more gradeful KeyboardInterrupt exiting
- redirected stderr to errorlog.txt
0.8.4:
- added better error message for missing config.json
- added automatic config.json creation
- added splash text with version and system info
0.8.3:
- updated matchloop with new regression format (requires tra_analysis 3.x)
0.8.2:
- readded while true to main function
- added more thread config options
0.8.1:
- optimized matchloop further by bypassing GIL
0.8.0:
- added multithreading to matchloop
- tweaked user log
0.7.0:
- finished implementing main function
0.6.2:
- integrated get_team_rankings.py as get_team_metrics() function
- integrated visualize_pit.py as graph_pit_histogram() function
0.6.1:
- bug fixes with analysis.Metric() calls
- modified metric functions to use config.json defined default values
0.6.0:
- removed main function
- changed load_config function
- added save_config function
- added load_match function
- renamed simpleloop to matchloop
- moved simplestats function inside matchloop
- renamed load_metrics to load_metric
- renamed metricsloop to metricloop
- split push to database functions amon push_match, push_metric, push_pit
- moved
0.5.2:
- made changes due to refactoring of analysis
0.5.1:
- text fixes
- removed matplotlib requirement
0.5.0:
- improved user interface
0.4.2:
- removed unessasary code
0.4.1:
- fixed bug where X range for regression was determined before sanitization
- better sanitized data
0.4.0:
- fixed spelling issue in __changelog__
- addressed nan bug in regression
- fixed errors on line 335 with metrics calling incorrect key "glicko2"
- fixed errors in metrics computing
0.3.0:
- added analysis to pit data
0.2.1:
- minor stability patches
- implemented db syncing for timestamps
- fixed bugs
0.2.0:
- finalized testing and small fixes
0.1.4:
- finished metrics implement, trueskill is bugged
0.1.3:
- working
0.1.2:
- started implement of metrics
0.1.1:
- cleaned up imports
0.1.0:
- tested working, can push to database
0.0.9:
- tested working
- prints out stats for the time being, will push to database later
0.0.8:
- added data import
- removed tba import
- finished main method
0.0.7:
- added load_config
- optimized simpleloop for readibility
- added __all__ entries
- added simplestats engine
- pending testing
0.0.6:
- fixes
0.0.5:
- imported pickle
- created custom database object
0.0.4:
- fixed simpleloop to actually return a vector
0.0.3:
- added metricsloop which is unfinished
0.0.2:
- added simpleloop which is untested until data is provided
0.0.1:
- created script
- added analysis, numba, numpy imports
"""
__author__ = (
"Arthur Lu <learthurgo@gmail.com>",
"Jacob Levine <jlevine@imsa.edu>",
)
# imports:
import os, sys, time
import pymongo # soon to be deprecated
import traceback
import warnings
from config import Configuration, ConfigurationError
from data import get_previous_time, set_current_time, check_new_database_matches, clear_metrics
from interface import Logger
from module import Match, Metric, Pit
import zmq
config_path = "config.json"
def main(logger, verbose, profile, debug, socket_send = None):
def close_all():
if "client" in locals():
client.close()
warnings.filterwarnings("ignore")
logger.splash(__version__)
modules = {"match": Match, "metric": Metric, "pit": Pit}
while True:
try:
loop_start = time.time()
logger.info("current time: " + str(loop_start))
socket_send("current time: " + str(loop_start))
config = Configuration(config_path)
logger.info("found and loaded config at <" + config_path + ">")
socket_send("found and loaded config at <" + config_path + ">")
apikey, tbakey = config.database, config.tba
logger.info("found and loaded database and tba keys")
socket_send("found and loaded database and tba keys")
client = pymongo.MongoClient(apikey)
logger.info("established connection to database")
socket_send("established connection to database")
previous_time = get_previous_time(client)
logger.info("analysis backtimed to: " + str(previous_time))
socket_send("analysis backtimed to: " + str(previous_time))
config.resolve_config_conflicts(logger, client)
config_modules, competition = config.modules, config.competition
for m in config_modules:
if m in modules:
start = time.time()
current_module = modules[m](config_modules[m], client, tbakey, previous_time, competition)
valid = current_module.validate_config()
if not valid:
continue
current_module.run()
logger.info(m + " module finished in " + str(time.time() - start) + " seconds")
socket_send(m + " module finished in " + str(time.time() - start) + " seconds")
if debug:
logger.save_module_to_file(m, current_module.data, current_module.results) # logging flag check done in logger
set_current_time(client, loop_start)
close_all()
logger.info("closed threads and database client")
logger.info("finished all tasks in " + str(time.time() - loop_start) + " seconds, looping")
socket_send("closed threads and database client")
socket_send("finished all tasks in " + str(time.time() - loop_start) + " seconds, looping")
if profile:
return 0
if debug:
return 0
event_delay = config["variable"]["event-delay"]
if event_delay:
logger.info("loop delayed until database returns new matches")
socket_send("loop delayed until database returns new matches")
new_match = False
while not new_match:
time.sleep(1)
new_match = check_new_database_matches(client, competition)
logger.info("database returned new matches")
socket_send("database returned new matches")
else:
loop_delay = float(config["variable"]["loop-delay"])
remaining_time = loop_delay - (time.time() - loop_start)
if remaining_time > 0:
logger.info("loop delayed by " + str(remaining_time) + " seconds")
socket_send("loop delayed by " + str(remaining_time) + " seconds")
time.sleep(remaining_time)
except KeyboardInterrupt:
close_all()
logger.info("detected KeyboardInterrupt, exiting")
socket_send("detected KeyboardInterrupt, exiting")
return 0
except ConfigurationError as e:
str_e = "".join(traceback.format_exception(e))
logger.error("encountered a configuration error: " + str(e))
logger.error(str_e)
socket_send("encountered a configuration error: " + str(e))
socket_send(str_e)
close_all()
return 1
except Exception as e:
str_e = "".join(traceback.format_exception(e))
logger.error("encountered an exception while running")
logger.error(str_e)
socket_send("encountered an exception while running")
socket_send(str_e)
close_all()
return 1
def start(pid_path, verbose, profile, debug):
if profile:
def send(msg):
pass
logger = Logger(verbose, profile, debug)
import cProfile, pstats, io
profile = cProfile.Profile()
profile.enable()
exit_code = main(logger, verbose, profile, debug, socket_send = send)
profile.disable()
f = open("profile.txt", 'w+')
ps = pstats.Stats(profile, stream = f).sort_stats('cumtime')
ps.print_stats()
sys.exit(exit_code)
elif verbose:
def send(msg):
pass
logger = Logger(verbose, profile, debug)
exit_code = main(logger, verbose, profile, debug, socket_send = send)
sys.exit(exit_code)
elif debug:
def send(msg):
pass
logger = Logger(verbose, profile, debug)
exit_code = main(logger, verbose, profile, debug, socket_send = send)
sys.exit(exit_code)
else:
logfile = "logfile.log"
f = open(logfile, 'w+')
f.close()
e = open('errorlog.log', 'w+')
with daemon.DaemonContext(
working_directory = os.getcwd(),
pidfile = pidfile.TimeoutPIDLockFile(pid_path),
stderr = e
):
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5678")
socket.send(b'status')
def send(msg):
socket.send(bytes("status: " + msg, "utf-8"))
logger = Logger(verbose, profile, debug, file = logfile)
exit_code = main(logger, verbose, profile, debug, socket_send = send)
socket.close()
f.close()
sys.exit(exit_code)
def stop(pid_path):
try:
pf = open(pid_path, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
sys.stderr.write("pidfile at <" + pid_path + "> does not exist. Daemon not running?\n")
return
try:
while True:
os.kill(pid, SIGTERM)
time.sleep(0.01)
except OSError as err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(pid_path):
os.remove(pid_path)
else:
traceback.print_exc(file = sys.stderr)
sys.exit(1)
def restart(pid_path):
stop(pid_path)
start(pid_path, False, False, False)
if __name__ == "__main__":
if sys.platform.startswith("win"):
start(None, verbose = True)
else:
import daemon
from daemon import pidfile
from signal import SIGTERM
pid_path = "tra-daemon.pid"
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
start(pid_path, False, False, False)
elif 'stop' == sys.argv[1]:
stop(pid_path)
elif 'restart' == sys.argv[1]:
restart(pid_path)
elif 'verbose' == sys.argv[1]:
start(None, True, False, False)
elif 'profile' == sys.argv[1]:
start(None, False, True, False)
elif 'debug' == sys.argv[1]:
start(None, False, False, True)
else:
print("usage: %s start|stop|restart|verbose|profile|debug" % sys.argv[0])
sys.exit(2)
sys.exit(0)
else:
print("usage: %s start|stop|restart|verbose|profile|debug" % sys.argv[0])
sys.exit(2)

View File

@@ -1,129 +0,0 @@
import requests
import pymongo
import pandas as pd
import time
def pull_new_tba_matches(apikey, competition, cutoff):
api_key= apikey
x=requests.get("https://www.thebluealliance.com/api/v3/event/"+competition+"/matches/simple", headers={"X-TBA-Auth_Key":api_key})
out = []
for i in x.json():
if i["actual_time"] != None and i["actual_time"]-cutoff >= 0 and i["comp_level"] == "qm":
out.append({"match" : i['match_number'], "blue" : list(map(lambda x: int(x[3:]), i['alliances']['blue']['team_keys'])), "red" : list(map(lambda x: int(x[3:]), i['alliances']['red']['team_keys'])), "winner": i["winning_alliance"]})
return out
def get_team_match_data(apikey, competition, team_num):
client = pymongo.MongoClient(apikey)
db = client.data_scouting
mdata = db.matchdata
out = {}
for i in mdata.find({"competition" : competition, "team_scouted": team_num}):
out[i['match']] = i['data']
return pd.DataFrame(out)
def get_team_pit_data(apikey, competition, team_num):
client = pymongo.MongoClient(apikey)
db = client.data_scouting
mdata = db.pitdata
out = {}
return mdata.find_one({"competition" : competition, "team_scouted": team_num})["data"]
def get_team_metrics_data(apikey, competition, team_num):
client = pymongo.MongoClient(apikey)
db = client.data_processing
mdata = db.team_metrics
return mdata.find_one({"competition" : competition, "team": team_num})
def get_match_data_formatted(apikey, competition):
client = pymongo.MongoClient(apikey)
db = client.data_scouting
mdata = db.teamlist
x=mdata.find_one({"competition":competition})
out = {}
for i in x:
try:
out[int(i)] = unkeyify_2l(get_team_match_data(apikey, competition, int(i)).transpose().to_dict())
except:
pass
return out
def get_metrics_data_formatted(apikey, competition):
client = pymongo.MongoClient(apikey)
db = client.data_scouting
mdata = db.teamlist
x=mdata.find_one({"competition":competition})
out = {}
for i in x:
try:
out[int(i)] = d.get_team_metrics_data(apikey, competition, int(i))
except:
pass
return out
def get_pit_data_formatted(apikey, competition):
client = pymongo.MongoClient(apikey)
db = client.data_scouting
mdata = db.teamlist
x=mdata.find_one({"competition":competition})
out = {}
for i in x:
try:
out[int(i)] = get_team_pit_data(apikey, competition, int(i))
except:
pass
return out
def get_pit_variable_data(apikey, competition):
client = pymongo.MongoClient(apikey)
db = client.data_processing
mdata = db.team_pit
out = {}
return mdata.find()
def get_pit_variable_formatted(apikey, competition):
temp = get_pit_variable_data(apikey, competition)
out = {}
for i in temp:
out[i["variable"]] = i["data"]
return out
def push_team_tests_data(apikey, competition, team_num, data, dbname = "data_processing", colname = "team_tests"):
client = pymongo.MongoClient(apikey)
db = client[dbname]
mdata = db[colname]
mdata.replace_one({"competition" : competition, "team": team_num}, {"_id": competition+str(team_num)+"am", "competition" : competition, "team" : team_num, "data" : data}, True)
def push_team_metrics_data(apikey, competition, team_num, data, dbname = "data_processing", colname = "team_metrics"):
client = pymongo.MongoClient(apikey)
db = client[dbname]
mdata = db[colname]
mdata.replace_one({"competition" : competition, "team": team_num}, {"_id": competition+str(team_num)+"am", "competition" : competition, "team" : team_num, "metrics" : data}, True)
def push_team_pit_data(apikey, competition, variable, data, dbname = "data_processing", colname = "team_pit"):
client = pymongo.MongoClient(apikey)
db = client[dbname]
mdata = db[colname]
mdata.replace_one({"competition" : competition, "variable": variable}, {"competition" : competition, "variable" : variable, "data" : data}, True)
def get_analysis_flags(apikey, flag):
client = pymongo.MongoClient(apikey)
db = client.data_processing
mdata = db.flags
return mdata.find_one({flag:{"$exists":True}})
def set_analysis_flags(apikey, flag, data):
client = pymongo.MongoClient(apikey)
db = client.data_processing
mdata = db.flags
return mdata.replace_one({flag:{"$exists":True}}, data, True)
def unkeyify_2l(layered_dict):
out = {}
for i in layered_dict.keys():
add = []
sortkey = []
for j in layered_dict[i].keys():
add.append([j,layered_dict[i][j]])
add.sort(key = lambda x: x[0])
out[i] = list(map(lambda x: x[1], add))
return out

View File

@@ -1,151 +0,0 @@
<Launch>:
orientation: "vertical"
NavigationLayout:
ScreenManager:
id: screen_manager
HomeScreen:
name: "Home"
BoxLayout:
orientation: "vertical"
MDToolbar:
title: screen_manager.current
elevation: 10
left_action_items: [['menu', lambda x: nav_drawer.toggle_nav_drawer()]]
GridLayout:
cols: 1
padding: 15, 15
spacing: 20, 20
MDTextFieldRect:
hint_text: "Console Log"
# size_hint: .8, None
# align: 'center'
# Widget:
SettingsScreen:
name: "Settings"
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: screen_manager.current
elevation: 10
left_action_items: [['menu', lambda x: nav_drawer.toggle_nav_drawer()]]
Widget:
InfoScreen:
name: "Info"
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: screen_manager.current
elevation: 10
left_action_items: [['menu', lambda x: nav_drawer.toggle_nav_drawer()]]
# GridLayout:
# cols: 2
# padding: 15, 15
# spacing: 20, 20
BoxLayout:
orientation: "horizontal"
MDLabel:
text: "DB Key:"
halign: 'center'
MDTextField:
hint_text: "placeholder"
pos_hint: {"center_y": .5}
BoxLayout:
orientation: "horizontal"
MDLabel:
text: "TBA Key:"
halign: 'center'
MDTextField:
hint_text: "placeholder"
pos_hint: {"center_y": .5}
BoxLayout:
orientation: "horizontal"
MDLabel:
text: "CPU Use:"
halign: 'center'
MDLabel:
text: "placeholder"
halign: 'center'
BoxLayout:
orientation: "horizontal"
MDLabel:
text: "Network:"
halign: 'center'
MDLabel:
text: "placeholder"
halign: 'center'
Widget:
BoxLayout:
orientation: "horizontal"
MDLabel:
text: "Progress"
halign: 'center'
MDProgressBar:
id: progress
value: 50
StatsScreen:
name: "Stats"
MDCheckbox:
size_hint: None, None
size: "48dp", "48dp"
pos_hint: {'center_x': .5, 'center_y': .5}
on_active: Screen.test()
#Navigation Drawer -------------------------
MDNavigationDrawer:
id: nav_drawer
BoxLayout:
orientation: "vertical"
padding: "8dp"
spacing: "8dp"
MDLabel:
text: "Titan Scouting"
font_style: "Button"
size_hint_y: None
height: self.texture_size[1]
MDLabel:
text: "Data Analysis"
font_style: "Caption"
size_hint_y: None
height: self.texture_size[1]
ScrollView:
MDList:
OneLineAvatarListItem:
text: "Home"
on_press:
# nav_drawer.set_state("close")
# screen_manager.transition.direction = "left"
screen_manager.current = "Home"
IconLeftWidget:
icon: "home"
OneLineAvatarListItem:
text: "Settings"
on_press:
# nav_drawer.set_state("close")
# screen_manager.transition.direction = "right"
# screen_manager.fade
screen_manager.current = "Settings"
IconLeftWidget:
icon: "cog"
OneLineAvatarListItem:
text: "Info"
on_press:
# nav_drawer.set_state("close")
# screen_manager.transition.direction = "right"
# screen_manager.fade
screen_manager.current = "Info"
IconLeftWidget:
icon: "cog"
OneLineAvatarListItem:
text: "Stats"
on_press:
# nav_drawer.set_state("close")
# screen_manager.transition.direction = "right"
# screen_manager.fade
screen_manager.current = "Stats"
IconLeftWidget:
icon: "cog"

View File

@@ -1,58 +0,0 @@
from kivy.lang import Builder
from kivymd.uix.screen import Screen
from kivymd.uix.list import OneLineListItem, MDList, TwoLineListItem, ThreeLineListItem
from kivymd.uix.list import OneLineIconListItem, IconLeftWidget
from kivy.uix.scrollview import ScrollView
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.base import runTouchApp
from kivymd.uix.menu import MDDropdownMenu, MDMenuItem
from kivymd.app import MDApp
# import superscript as ss
# from tra_analysis import analysis as an
import data as d
from collections import defaultdict
import json
import math
import numpy as np
import os
from os import system, name
from pathlib import Path
from multiprocessing import Pool
import matplotlib.pyplot as plt
from concurrent.futures import ThreadPoolExecutor
import time
import warnings
# global exec_threads
# Screens
class HomeScreen(Screen):
pass
class SettingsScreen(Screen):
pass
class InfoScreen(Screen):
pass
class StatsScreen(Screen):
pass
class MyApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "Red"
return Builder.load_file("design.kv")
def test():
print("test")
if __name__ == "__main__":
MyApp().run()

12
submit-debug.sh Normal file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
#
#SBATCH --job-name=tra-superscript
#SBATCH --output=slurm-tra-superscript.out
#SBATCH --ntasks=8
#SBATCH --time=24:00:00
#SBATCH --mem-per-cpu=256
#SBATCH --mail-user=dsingh@imsa.edu
#SBATCH -p cpu-long
cd competition
python superscript.py debug

12
submit-prod.sh Normal file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
#
#SBATCH --job-name=tra-superscript
#SBATCH --output=PROD_slurm-tra-superscript.out
#SBATCH --ntasks=8
#SBATCH --time=24:00:00
#SBATCH --mem-per-cpu=256
#SBATCH --mail-user=dsingh@imsa.edu
#SBATCH -p cpu-long
cd competition
python superscript.py verbose