From d634702504db41df3f3cdafa58079ac1e295a757 Mon Sep 17 00:00:00 2001 From: Daochen Date: Mon, 11 May 2020 00:36:49 -0500 Subject: [PATCH] Django init --- .gitignore | 3 + README.md | 35 +++++ requirements.txt | 4 + server/manage.py | 21 +++ server/server/__init__.py | 0 .../__pycache__/__init__.cpython-35.pyc | Bin 0 -> 162 bytes .../__pycache__/settings.cpython-35.pyc | Bin 0 -> 2386 bytes server/server/__pycache__/urls.cpython-35.pyc | Bin 0 -> 1024 bytes server/server/__pycache__/wsgi.cpython-35.pyc | Bin 0 -> 581 bytes server/server/settings.py | 121 ++++++++++++++++++ server/server/urls.py | 22 ++++ server/server/wsgi.py | 16 +++ server/tournament/.views.py.swp | Bin 0 -> 12288 bytes server/tournament/__init__.py | 0 .../__pycache__/__init__.cpython-35.pyc | Bin 0 -> 166 bytes .../__pycache__/admin.cpython-35.pyc | Bin 0 -> 211 bytes .../__pycache__/models.cpython-35.pyc | Bin 0 -> 891 bytes .../__pycache__/tournament.cpython-35.pyc | Bin 0 -> 3597 bytes .../__pycache__/urls.cpython-35.pyc | Bin 0 -> 424 bytes .../__pycache__/views.cpython-35.pyc | Bin 0 -> 2587 bytes server/tournament/admin.py | 3 + server/tournament/apps.py | 5 + server/tournament/models.py | 37 ++++++ server/tournament/rlcard_wrap/__init__.py | 15 +++ .../__pycache__/__init__.cpython-35.pyc | Bin 0 -> 482 bytes .../leduc_holdem_random_model.cpython-35.pyc | Bin 0 -> 2194 bytes .../__pycache__/tournament.cpython-35.pyc | Bin 0 -> 4087 bytes .../rlcard_wrap/leduc_holdem_random_model.py | 46 +++++++ server/tournament/tests.py | 3 + server/tournament/tournament.py | 117 +++++++++++++++++ server/tournament/urls.py | 10 ++ server/tournament/views.py | 60 +++++++++ {server => server_bak}/index.js | 0 {server => server_bak}/package.json | 0 .../sample_data/doudizhu_random.json | 0 .../sample_data/sample_doudizhu-test.json | 0 .../sample_data/sample_doudizhu.json | 0 .../sample_data/sample_leduc_holdem-test.json | 0 .../sample_data/sample_leduc_holdem.json | 0 39 files changed, 518 insertions(+) create mode 100644 requirements.txt create mode 100755 server/manage.py create mode 100644 server/server/__init__.py create mode 100644 server/server/__pycache__/__init__.cpython-35.pyc create mode 100644 server/server/__pycache__/settings.cpython-35.pyc create mode 100644 server/server/__pycache__/urls.cpython-35.pyc create mode 100644 server/server/__pycache__/wsgi.cpython-35.pyc create mode 100644 server/server/settings.py create mode 100644 server/server/urls.py create mode 100644 server/server/wsgi.py create mode 100644 server/tournament/.views.py.swp create mode 100644 server/tournament/__init__.py create mode 100644 server/tournament/__pycache__/__init__.cpython-35.pyc create mode 100644 server/tournament/__pycache__/admin.cpython-35.pyc create mode 100644 server/tournament/__pycache__/models.cpython-35.pyc create mode 100644 server/tournament/__pycache__/tournament.cpython-35.pyc create mode 100644 server/tournament/__pycache__/urls.cpython-35.pyc create mode 100644 server/tournament/__pycache__/views.cpython-35.pyc create mode 100644 server/tournament/admin.py create mode 100644 server/tournament/apps.py create mode 100644 server/tournament/models.py create mode 100644 server/tournament/rlcard_wrap/__init__.py create mode 100644 server/tournament/rlcard_wrap/__pycache__/__init__.cpython-35.pyc create mode 100644 server/tournament/rlcard_wrap/__pycache__/leduc_holdem_random_model.cpython-35.pyc create mode 100644 server/tournament/rlcard_wrap/__pycache__/tournament.cpython-35.pyc create mode 100644 server/tournament/rlcard_wrap/leduc_holdem_random_model.py create mode 100644 server/tournament/tests.py create mode 100644 server/tournament/tournament.py create mode 100644 server/tournament/urls.py create mode 100644 server/tournament/views.py rename {server => server_bak}/index.js (100%) rename {server => server_bak}/package.json (100%) rename {server => server_bak}/sample_data/doudizhu_random.json (100%) rename {server => server_bak}/sample_data/sample_doudizhu-test.json (100%) rename {server => server_bak}/sample_data/sample_doudizhu.json (100%) rename {server => server_bak}/sample_data/sample_leduc_holdem-test.json (100%) rename {server => server_bak}/sample_data/sample_leduc_holdem.json (100%) diff --git a/.gitignore b/.gitignore index 4d29575..84e5c0c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ npm-debug.log* yarn-debug.log* yarn-error.log* + +migrations/ +db.sqlite3 diff --git a/README.md b/README.md index 3970716..beec914 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,40 @@ **NOTE: This project is under final tesing. The one in the repo only supports the visualization of some sampled data. The full version will be available soon!** +# Server Setup +Install dependencies: +``` +pip install -r requirements.txt +``` +Migrate the databases: +``` +cd server +python manage.py makemigrations +python manage.py migrate +``` +Run server: +``` +python manage.py runserver +``` +The default URL is [http://127.0.0.1:8000/](http://127.0.0.1:8000/) + +# REST API +The definitions of the fields are as follows: +* `eval_num`: Integer. The number of evaluation times. +* `name`: String. The name of the environment. +* `agent0`: String. Model name. +* `agent1`: String. Model name. +* `win`: Boolean. True if model in the first seat wins. +* `payoff`: Float. The payoff of the agent in the first seat. +* `index`: Integer. The index of the game of the same environent and same agent. It is in the range \[0, eval\_num-1\] + +| type | Resource | Parameters | Description | +|------|---------------------------|------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------| +| GET | tournament/launch | `eval\_num`, `name` | Launch tournment on the game. Each pair of models will play `eval\_num` times. Results will be saved in database. | +| GET | tournament/query\_game | `name`, `index`, `agent0`, `agent1`, `win`, `payoff` | Query the games with the given parameters | +| GET | tournament/query\_payoff | `name`, `agent0`, `agent1`, `payoff` | Query the payoffs with the given parameters | +| GET | tournament/replay | `name`, `agent0`, `agent1`, `index` | Return the replay data (only support Leduc Holdem for now) | + +# AAA This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). ## Available Scripts diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e074cb5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +rlcard +Django +tqdm +tensorflow==1.14 diff --git a/server/manage.py b/server/manage.py new file mode 100755 index 0000000..1c81878 --- /dev/null +++ b/server/manage.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/server/server/__init__.py b/server/server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/server/server/__pycache__/__init__.cpython-35.pyc b/server/server/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68c34cffd421b02b202cc3c9b7816ac0177a61b8 GIT binary patch literal 162 zcmWgR<>l(D-4VwC1dl-k3@`#24nSPY0whux7=kq!{Z=v*frJsnFMs`v{M=Oil*Ihx zjMO}Rm(=3ylKcYwqMYQ!q7>cYjQsMH{PH{uesOA1S!$6!l!}kf%*!l^kJl@xyv1RY Qo1apelWGUDs2GSD0DGY;MF0Q* literal 0 HcmV?d00001 diff --git a/server/server/__pycache__/settings.cpython-35.pyc b/server/server/__pycache__/settings.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7383c0fdfe71db7baf1415fc8b43dab3a4b7cc5 GIT binary patch literal 2386 zcmb7GTXWM!6h6MhcANxgpg^Go0WBl}%OzaObQp@TMeyKDCbE-O4`^iV+FnN&N4p|K zul$Psg#Ls67QObVf1yu3lI_^zFw-@{5TJibse}1^P3h)=q{oop2 z<1c@i0w4f7K2t!_V5dM&0ZqX$4a3YCAq#W~KBp$Po&%BrJr5)cdI9=~vkYVj2xpRv$Ys#cdIiYWK(5A6_lP@WWKN zKNTLt0^;jPYy-y2d($i?Cgb*XO(N~G?I^nfHGC6hSJmAEi{G4XsL1sp-73FfxEEkEAI z@VAKRcs`Ywi|~#qnCD7(ivh!g%%+bpB`pqw81bLWW#U;}9w(Vnuso+s-7+GUg*Rdr zFHZ@V$M9l6rCwm$lFhh~yxwd>rb{ppWxn*$v;)fjPcEPK<`VrK_hB>KE{WGp?`e;1 z_IsbgkI!u9#nEAZbL&~~q3aJzrIW3|-oEdj91-eld}8j4jXUk|%6LDr<+;LVT{$UU zczID9h(UOBK^ccoSBR4l<>9pjBd45WHP0FxG?;yixUm=^u>MwDb*>kM7x=E}AbePw z_&JOan;x4!l{vKnpNSJ$n+T0lTljPlc0xp+i`T}wxv0&vN$}M=o-0?9KmXy%{hnOG z$3COSbFM!va51rr^E?z>;})5fblzOx;wGj=n-6Y`3pp3{{0p0~nRPfctwU^o`Pa8T zmb5jB+nmqEt&HbN4t$$O`8P`Cz1pmXwcD<>nwq|zbjl}T;M7>i+Vgq1v50=wM<%oz^uw)lc>44RCrE@3C%&iM z92fix$nlE^pDZ|^7WoSSQ(Jg#QmbR$XRs*7eG+AxN<$5cXqsrkcMD{aRvDR`AA3GA@PuF_$s>1=fFj~q4FuJg!)!Aih5fOI z=ZCM(i_~B)a{{MM-M$#i;(s}B{CF~UCmd%0ug?q63>@k+>ny?&bxQ%)Go5xNER^vi z#}O%SUXSvIfoHH`L}`yl*^wy*Say~i6j9#n@H6Gr&b{8>-HrFZe*g5S2k-;7z6jUP@V8SOH~>yO03Jda zfDB<8Lg4p3D0?6ym_{J`FzrJi`oJR)5%50T25=jKKN)}sVL5>1(4Q<2U<7;!?~@VJ zA!ZTgN*MC--5YYM)x22LhPgtkIR20ea#5SIV$KPp>;)+c>xj{{6V_j_#A$L>h?Pyr znKndfBS@j<+Q=4yRHa~65G%waCivyfRdzxt*O^WElBtERj9!Y&rJ0sgD0-Y8Q>UvU zv(yJuOmAuY@(YuQWhe1jtuoJUowfyioRa696Q)QZD{b6_kh#&4$m8 zC8K~Xg?JUk<_F{PVW%tCQXCS+q&OM-^*D)7OJ?oSB?{wPsQ+W3T`r6#lD0-|=)6L# zmi-;s`1q9BnFl#Y{$g~lva;rdTA&GSJ})i9Vs897Z;c^H1lCT+eaZTi{zu9rRHr{XL z=*`}rO$%@{Xm8QC$-QPcn_(NxX4Cr}a}?}MacQupq1oAzWAK52@vo|hY~e%`d6CV| zR^h*aiG7eCe!Zr?(v&lu<=B!hg#C;yNllqC!;fsPS6r{uKl}AVqTS?Eq}6pZdLlKi UOYw9Mq3sBVLGU2h?>!8D1JH0fXaE2J literal 0 HcmV?d00001 diff --git a/server/server/__pycache__/wsgi.cpython-35.pyc b/server/server/__pycache__/wsgi.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e9900819e73e1d120eca8b258db434546077359 GIT binary patch literal 581 zcmZWl&2AGh5T4y_lWL)&5~yciBhj_gBSHvJN|XZWAw@_zurce&#=&c^Y&W5mdaAhc z9=rih!eOtRcm+<(Wad`|sd5lLkoGG&Ob+6I_4)LePCP#PbT227VB)cy(Q(iT3GD`86ePg7wlj)tFR zr+jHQ!E%YUw$~M!z&E~BJpD!g1Cv42JSs8dtuNn^(HsxYUra_9`Sk4aay%JL^S2kn zcW=&a9(2QJ9z#&3^n-rW&vR0c=S^&VbJXd`3X-3-U0qB(O&`r#Icu7f3MDSYl@86l z9l~$mQcB#y@7E-{LN0|ZmNdl>{ik4S?sOrXJn=MWr^yOYNMUM+c6UpEI&yU%}i QK>d9Sz4(576hDmr04IL4?EnA( literal 0 HcmV?d00001 diff --git a/server/server/settings.py b/server/server/settings.py new file mode 100644 index 0000000..11bb659 --- /dev/null +++ b/server/server/settings.py @@ -0,0 +1,121 @@ +""" +Django settings for server project. + +Generated by 'django-admin startproject' using Django 2.2.12. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.2/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '-t@mf4fi)gfxzv5lm8qkg)*5u^brj--y*ul2&ryqdem(xin8(!' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'tournament', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'server.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'server.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/2.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/2.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.2/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/server/server/urls.py b/server/server/urls.py new file mode 100644 index 0000000..835cfb8 --- /dev/null +++ b/server/server/urls.py @@ -0,0 +1,22 @@ +"""server URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/2.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import include, path + +urlpatterns = [ + path('tournament/', include('tournament.urls')), + path('admin/', admin.site.urls), +] diff --git a/server/server/wsgi.py b/server/server/wsgi.py new file mode 100644 index 0000000..b238574 --- /dev/null +++ b/server/server/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for server project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings') + +application = get_wsgi_application() diff --git a/server/tournament/.views.py.swp b/server/tournament/.views.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..3278d920b51c6591cce462cc02684c650c49b514 GIT binary patch literal 12288 zcmeI2O>f*p7{{j|6-o(3tyEqQ1Cj7<GTd^|<5N zEXzw<3HS)yK!_73E*yXlz=<12BrX-=!i@`8_|J~*9lM(}9FPEwrT=x6_p4~8sNH3vS2wYyOmuB@^An&jDvNCIDk zXY(PSgnW|Tk)O%I%pt+WIzfd+xGjLts4M4o%L+fg;k zPd`OZoqVHVWV4olC143y0+xU!UBlR4EhxM5DK6r=%)vfhAu!aLd(#-&{xL^ znLrnzC!r^x$DyOp?++02BlHDy19}Gf;~2((K8FPK5_A%}eLo@JKp#V!&;{r;^efi* zHFOiY44sD_h1A+lL-w%*ECEZv60ihl@dzey`Ha3SW%e4&GoI$G)oqiqTD>zb_xD(< zURW7q{**^iPrv%1Fa0e?XPoVQn)m};b?erf=rU*9B~{O6VpiQ*(4^CBlF=T0bvCD# zx>HwgqDssL5f{{$IgQgIo6lCVTAR$^Kn{Xsi9hWPFhW5=m+VVHk83t4vF*cP5~rp$ zvgT4uTC^Z+Oy+QWn+@)uTa6N@A$!N1&a9w0p#hw+0V3KJM(>LpQB^B9s7%ud+N~bn z*=2#uy(ms36Z5XyUdR$A&7G>o{yX;bQQg``z%n+gOPVcZ<8&m>lk` z#(omN%S7%~>6Wvb^VD%Mt$ms;_T8B?+KK%z4vfK!LX7y{H8x$X7K~MT114K2Y*Tf9 zkx&~(^bWMsTU4PY@D1*ny@_ zbyZ58cD#xZ(O%$~jRkxCU&dD*gTvBQ8)_Cv=S!`Muqg(f4zHDm%1~1sceP2>8SAMJ zSBJz-PqQtuU7hW^*gz_r%|7Sj&9WG)b{4glwySY=}2Ka;)t|)X{I)wTYTph z7U8a+4!9R^!Ah$tR)}2pQrLt$rG*irY8FHMHYsh)-zhaC+_4uj7|Uu_g2APN`~?w9 B1mpk! literal 0 HcmV?d00001 diff --git a/server/tournament/__init__.py b/server/tournament/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/server/tournament/__pycache__/__init__.cpython-35.pyc b/server/tournament/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c65b9c8ae7646bea1afea72c407b1edcd259d55 GIT binary patch literal 166 zcmWgR<>i{yup^EE2p)q77+?f49Dul(1xTbYFa&Ed`mJOr0tq9CU%~nr`MIh3DT(>X z8L4^tE~&-YCHV#VMLEfdMJc+)8TsWY`Q>>S{NmK2veY8|lKj%5yu{qpyb}HR_{_Y_ alK6PNg34PQHo5sJr8%i~Aj^t@m;nGvDJ>2F literal 0 HcmV?d00001 diff --git a/server/tournament/__pycache__/admin.cpython-35.pyc b/server/tournament/__pycache__/admin.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a9122752c104fc3fd5fe9523fa9f1e13501fa459 GIT binary patch literal 211 zcmWgR<>fkAza!3`fq~&M5W@izkmUfx#Uel=1&A0Kau^tL85yD&85mQT7=ksKUjk(q zG#PKPCZ^m}#sl@w(r6@d&{$xy@$q`<_l0R4>o+*JLP#Qfxp z)I5Ec)Z*-t`~v-=oaDr!6y4&C{PL9i@;nTFacWUnYLR|PerZu&Vs2_)i9Xm$y@JYH U95%W6DWy57c8owvih-B`0Fw_miU0rr literal 0 HcmV?d00001 diff --git a/server/tournament/__pycache__/models.cpython-35.pyc b/server/tournament/__pycache__/models.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff936529cd0d6d0d0342f14efcc1b9a6f5cafe05 GIT binary patch literal 891 zcmb_a%W~5&6uo{XcAZi>kePmh7u2w4m=1K36&WC1d4Wfb)I6$4sqBzs3;Ya!z=yEX zmQ{a&75B=t(;+O8t>ddB`P`TKypjDVVrkvQ44a<#!JnGtS7X*8yGlf0QRGnfm>ZAiS0 z=8B80joDPF=J}uR3!A;xS_-DxqrqmbY&wvdH7yaZ*iK(v+2lfOTdItWSV^|~2IdJm za`5YYG1E&?aHc0Sp^9@+UpIPH7&&2vKdWbY!}Uh(t!rUE2~#wBZ74?76m6SMS35)9 zp;;dyWd3o`K3R|jZf}D0{h)(qIO`7x|EHB**Q|uvG|odCzjK8!Av!P-!YEHohZbFe zgn$ZfQi2159sxyf9upiB+?TAio)XtbIKf$y(p{#G9p#Zt_=2gaKINBfW23iplU)hi WnSV*z?#uRWyz)qwVm|Uu`o94mfw>j{ literal 0 HcmV?d00001 diff --git a/server/tournament/__pycache__/tournament.cpython-35.pyc b/server/tournament/__pycache__/tournament.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a72ad47425969b117e91cb99e9d0ad9e520364f GIT binary patch literal 3597 zcmZuz&yU;26@EieltlgBwVkSVQXxU&sLk#=C<+wG!f@e5>K?Kv;G_nGI0RQ5X{n`1 z?U33Zf^;Z0_qMnG1qJ#C6zH*sp8E$3ie7r!ThBh!{oYX0u2YlZXx^JQ^WK}8@0+<- zue)FW^RM4JZK8kEt;a_F3BL62C<6QhMMV8gT~J>by+x5l6N~y5iIrV}`Zfgx3T%ps zG;yf!koaX#q`;x?FoHv}L|3pXQ&6Iy%*uX+q)S1CPApP?qrjzpl>+=~6x3-1;~L2_ z$tuYjUBO+QWSzzhxQ3^9lRCb!JY@*13C1gtUF9pH#<+d z)5yP+syl+y)a~ASzJS3&GV30M^W)hk-RxNA_R>%NI7_>;6bdL)^z2TOKt`MH1D+jz zIAjj}IllCL6eC1M^zsL^6qFH-1&tBEne{(dbc$K{GxZ9J`)J1unrb^r{GexPYxj{Z z8=V&hsss~Ly!v|YIGM=3z)uFpGTu9o=}DGM_wtq5Nsp8BAUTi!Pfn#elWH&9%=oS9 z?)37NyB~#VHb^GZ$6Fje=Tf2h!y*rf%qkH{<5x{d&};L!d8 zW1&_;&CCaf&5H6yfsj~Hfuc+>H<}0z&w|?_nF+LUZ)V%o%fWRNg?$p0bhQrUa&Ge&-VI0T{?Vu&j9u#d|k_(rnw|SEymh5Eu~e9wh?67ukxT?uG8W~S9p-TS2fof z;rl>yB7YVSj_)9Z^fMGxXbK1KHr|>jh=<~-Xo|WhSsiHW!WC`24Sub*#Tu4faaYXS zw}6?Cde|#6l6i(bPrIIn9A^>NYo2#H^P{{)G2f^iE^cVR)R+rY5d||q$}Cy4ny%3d zcscpm#>d76@>8%@&a>EcoAW1R_=_c=i|w_BykIV{4Hpzm>CnYT7Lb(zwblktTNdER zyBfzYP;U+}w!lb5HZms;+IXWw2OtuCV=-cZL)HMmIT{W6I=~iV0M19?4hY!)7e5wk z2?{`#|1xzT0+?e00OExiu|~_fiKM}8iv}P2#^=hmO3D?$5w`%S@wRaf*`R5q<)oW* zkx^DR&A1XEhnEB6p+(C!WldVtSqnV!^`b9=yR_V*_ybzBIh>$DofC)Dxq#iGMICN* zD7eQ~izba*>>sv4ixyiHnzG34bPUctFIMj7?JDyUl!_ z{snCCy*b?iQDL-g+RwIVjHEG*U`$Y0kweKvGxi;xUv|lv*`z+VKy4f?*c9$#WRuG< z&+kl zgJZt29|TX=>Sn-K037^x(aYeXXDL1n)rV_EjuwLvKKGvBTc6tR-H_1R4(q;~Q|7PY zVWQn*KMp*;)}{RlAMnp0God7B@)?fzL|yhPEBoLA>;=7H)N8&X=r$)C$&nv<{vZpJ zI5kY$uTE8R$84h{Xs`5x^JM|9$=X^)e4#1`|SID9>F%9?Qx2+i@|I%MOMbQIaku& zc7DS#-U=LGLB?n5W8<7Ve%Sp6;+W)(|ZyD9Q(=YD=dJ!aUZKSWVO;w@3LTGqWswcQ$~sfm|${{yGZ BG%f%D literal 0 HcmV?d00001 diff --git a/server/tournament/__pycache__/urls.cpython-35.pyc b/server/tournament/__pycache__/urls.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c9280eae9fea87df7301c82fe0f486e321a2331 GIT binary patch literal 424 zcmZXPu};G<5Qfi5nxrX}Sl}Hx(7XTw24)!8I)JSD+E5%joRd}=VBu+a1D?fVW9lm~ zaSp14gnj;f_xWW1KAldBm(P#;O9Ai&e@4#v6)*S7qBsO-fLg#pfKU;r7<2@642u{9 z3Q!4P44VYhDCBR^0Mh|7;YbfK8(=!X>;UrtW&_LvTqm%|L5<;VR_xgW%!E%G*;aeD z8j8{O5qHj~gpHQHPmHY5r&@MqS^1;q4yk`=WN%k1U;I{U?zowa{X}h~S=)I>+EK)} zd7y+h8U@LMgzwXs#ZS14pKXzhdk30^gCO6xWo2tDm9)zWO?i#(skKc>dMQbrxytU8 p-I;&2L)s#ht?ei{Hf^9M}aXo>&; literal 0 HcmV?d00001 diff --git a/server/tournament/__pycache__/views.cpython-35.pyc b/server/tournament/__pycache__/views.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1825b4ec8cb6da302d55d93030ab7a228b1b284e GIT binary patch literal 2587 zcmcIm&u<$=6n?Y2-u15SBu(4UP*h6!(ON*#-m41KRHYJ>s;N|IMX|QtO=4$%xHIdf zv62G{0))hgzk>e&{*}3K;M6;(p7`F3?IdcsL7W-CH}huZ&3oVb#w(ppH2L%QZ(lZv z{-P6qF67V9)F0?l{0qv73PG_T!Ma1aLxoGRYju}$kBSDx4Xb;U`&0xJ2hbao`jj`R z2q_M!h$xQiXh3<3iZ;b}Zqn1u7OPUW6V}8qxPe@e-viO4~+0LurT71tTw0 z)}Y~8N*5_z;*leGd5+REwAo#L3HPZhv@f$V%_OAu7j->)n5j`!stkIomPx6Sem$s4 zR#hekNj{ilQoR(s*wNnIq{y`YAla|BwxIhm?q zKCk1y04+qjji$ascR(~W!Q6F79vW3}ELRW3OmU$&GsT1A&Xfiek7|d8E)6|ic7Vm0 zb}04ez$L`_z@sDb4j~{W4LbCx_UXXqm~0|#n_d6DcJJPKq&;?3`^h%^y*~ZEp&J84 z=|wltev#EXRVv$XTJkk?P(2-H{aR^vJF7XKqdeJ{j1!m#GJ7`8R4qGfzrfuhcT4EB z*p9=Ys>)uP)X8ro-@@Rl2kSdkk*%jm)!)g=^^HvJ*41d;M)p&+Q|+bIUiq4i>^#rp zdOeTz`tw1yr`AUM@*K8pp(#F;#G>d-KUYO4%~)03->O3Q)5*N-(vL)2CNGHY z4@9*v1`bCNu|Fc(fP|FQ9tU}d2n+g!2zjdm8a7QjkQBhaO-GL4@sQIr&qC+EiR|1V z2R?XcXW5|-(G3h%o?PTptaC#kMDPyie|6}YPn#x^UB@Pgmjav4+I8*jX8TGzEZ+fHV-kvxN)w8ws#OK1G3X%OEu1G8<}Yc`1U$Fz9z>-arzk~*Tk~8Amm5T=GoxgXH6j! zr{R(PNANgu3}8+Jqw#+ML$2Z;@@;glAwyoo=q0onBre-n*^Isk6!IP3$EHtShHN4D z9!q#h$Rtl*VTm&*-{kHJ{;0pf+*>Q>a)~Df#qCO%q4B0@`(Z5W* z*k&@`c+w;AFqShpg9^aqOwf=(|FC zfvB6=^Ca(;<3f8(5pN;@$=H$aa>pDjeRSQ9t!;Nu+R~Ox&62B5`*|`h`#Z;FZjhq= zG|Mv-I|E32Dgn2uJQUVx;SD-lzC0!wgu@_3wg#&$Q8D1*;zB9#mJH&lb>Nk z`7tC$qWT0KIg8>fUW_YZ6`zh+64CtA5exGXmd(oh-ShEMI!wy#Y7Os|to!3yNoG~u znhx*ar-r$N4yPmOQ^`CZ&n)_t%q+Y4MTG!N$&X_Yx9nrs+mp#iGSF@KqT|QU2Gsi5t(at(!M-)Hu&>@y`^+tCw(Fe4G_$1${ee2kquR(4+nh literal 0 HcmV?d00001 diff --git a/server/tournament/admin.py b/server/tournament/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/server/tournament/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/server/tournament/apps.py b/server/tournament/apps.py new file mode 100644 index 0000000..cd8eb1b --- /dev/null +++ b/server/tournament/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class TournamentConfig(AppConfig): + name = 'tournament' diff --git a/server/tournament/models.py b/server/tournament/models.py new file mode 100644 index 0000000..e33e1b2 --- /dev/null +++ b/server/tournament/models.py @@ -0,0 +1,37 @@ +from django.db import models + +class Game(models.Model): + # The name of the game + name = models.CharField(max_length=100) + + # The ID of repeated games + index = models.CharField(max_length=100) + + # The first agent + agent0 = models.CharField(max_length=100) + + # The second agent + agent1 = models.CharField(max_length=100) + + # Whether the first agent wins + win = models.BooleanField() + + # The payoff of the first agent + payoff = models.FloatField() + + # The JSON file + replay = models.TextField(blank=True) + +class Payoff(models.Model): + # The name of the game + name = models.CharField(max_length=100) + + # The first agent + agent0 = models.CharField(max_length=100) + + # The second agent + agent1 = models.CharField(max_length=100) + + # The average payoff of the first agent + payoff = models.FloatField() + diff --git a/server/tournament/rlcard_wrap/__init__.py b/server/tournament/rlcard_wrap/__init__.py new file mode 100644 index 0000000..5bf495f --- /dev/null +++ b/server/tournament/rlcard_wrap/__init__.py @@ -0,0 +1,15 @@ +import rlcard +from .leduc_holdem_random_model import LeducHoldemRandomModelSpec + + +# Register Leduc Holdem Random Model +rlcard.models.registration.model_registry.model_specs['leduc-holdem-random'] = LeducHoldemRandomModelSpec() + +# The models we are concerned +MODEL_IDS = {} +MODEL_IDS['leduc-holdem'] = [ + 'leduc-holdem-random', + 'leduc-holdem-cfr', + 'leduc-holdem-rule-v1', + ] + diff --git a/server/tournament/rlcard_wrap/__pycache__/__init__.cpython-35.pyc b/server/tournament/rlcard_wrap/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7fb4e1f84ab3b80a063b4d48acb952b5f158c52c GIT binary patch literal 482 zcmZWlu};G<5Ix6jS|CN0KuF~eI)sS5LJUO$sRgOsGGIlqX%dn+veQ=0$~W*4`~hFU z%$${}zre&L>Cg(xKD~SI^zP0Vz25Qn*XQ#)0r-KvLlNKN(=!YlFM$}qMPLA@5EDoY za19{BfHwdE5K)L)5VavPfwy23VtJ=Rybauh1qFd=2S#W$A9lCs3y)ju3qw*~P6S{2 z_cG=pnRzLf$y9O?&oki{XK|(3K`q*A$Gr{D4u*SlFxU!rEtt-O^OC?<8PIHoR-rcdL$340jNKR|WR zqz=E#31lK1?nyrosWTS(HJ6#w%wg+5uDM*N|8gzVN+>6nOO<+wNb_9f2l1D7U{PJ)HEoeOaDQC3xS?`D*6v{>daD-?N|xn9q)4<-+VLbZfvx>fBg01-!8yEaO1-@ z9O6j7M-k$m1rlIX&25kt%xoChV9}Wa(t()^BNwcr(1oxDzu;0q1XHuEx^FD%6lh%9IDyViHI{?*1lDtkO7@8KN}~9IMN*y0{yYbH*^Cv zg*K@lIphxdKy%~C(5sgp9*Zy!zE(06v&x9kJxoLpSg49V`cL|w;YhnEQ0Gqo93ZPE zXa&$;dr)jkQnx!b`gXPP+H=b0j2z}sSa#RjD?1!R)0aF^kqOaFg&hA0x`pOmC;h3K ziGJv-U@GGNbCI5BD(Pz(_&VH8r)nOmd3n&`C5F%GHWEEtEBNA^_}aAgtq zX=llP+Ckno5tf#&qq5=wd&;W3Fat}Q;dcvNGX9K=KS7Zpy2y14P!j^2p=Fz3K64Oq zi}>oAWzBFGEjwt+EgrFB#OtmhGFEg9NfvZ2+kTKmD&}!M8(`_wEB=-4%s&^JvaR1o zQPzAa)3TjN|59kWy-cqo;)^#irVKp5ky6ayY+4WBn%%n;BYF`CG*X7*6~NelfU*B- zF!{~Ef|xwVG4!0`KXxQC<}(?k8B=3syiM6yX(s$&$`X}E6ef#eyp>G_n;?tY27LnM zL}XY`>E3FCHWx~ENU67niMy@+`t?9%Vvl`AhRhp=)tk$ZoeFlAqeC(}7wqJCaX62% zDN8evFzh5uT=XvE7#(8WK6U7rY7gF|C=Xcn$O+bBsVq(hihfSgiK?Lx-4KM33 zH2J}@q?~wmY4^S?Eskrd&nkCR8n4^?6k(ud$-(EiPAUB@C?2n`%U*>~Z(pjwm+1jc zmaox94Ou=B`XQ>gX=ph&J)mA`c(k+y?c(Ei+FFH999gv?s%Z1uVi&L2H*pvRekRy_ zDlpHQ<*C3zm?Pq}OORKLzfRxUs5-zRyQT${+lxKZveI7F(5XJlx;i}*L1ucW YQM1l!+1#&M^?|8rW7^uXw(M@}e^QPBLI3~& literal 0 HcmV?d00001 diff --git a/server/tournament/rlcard_wrap/__pycache__/tournament.cpython-35.pyc b/server/tournament/rlcard_wrap/__pycache__/tournament.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c728737df42d670b3628edd838dbeaa4e555a6c2 GIT binary patch literal 4087 zcmcIn&2QVt6@NoXltfW>Hc9O$&WF0$W>>90*4Y*Tw%K$St9nms?8ZS22e+2RH7vvMQvbLa>AkQE#N4`P*9JO*JzVPzo z73eu;6-egk9P9#lCV53>woH;m@=A1Qkop739Q8`nE0b5IbI7yiIF{yANLtjhdH-gEsFYpx{oU`U2Y0_6q^p5Q(Y$wyV50GpAP$jZbk$4?!f9f*GK& zWNOcI=#rz%loo8tEPyp7>{Cvxr{PcqZeIrR3k#Ckc@Vz%$@k~DqdQO}mHV71COR|N zt|sm?B1cec=!QWt&LYoUoF{fZ7lJ1g-oQ8Cz%Npq9%zATyuL&+&JPDX>01=z6leVk z#rAyPrnoxauhLmgE4aY4SD@aaZj>~&2yX(Wu&O=t;#g&Vtax$Eo{r&IcN)c!S8vLF z*N^M_p{mCxVSV7c&!nn%aJrFIpS!j&p&1VA&F<)6xLS`7WIA8EksHKOeHeiOW`vdX ze&|U*Ti#}u;LE_x?`H>h^e#vTuZ3vu295DPV2Plfejl*xw+0ottTSpP5)jxsSzlb7zsLD-iYo*T9gWU$ec(P118Hd2pViw?pQFFXle z>qk-@OSKVa-Zh!woG5oN$6g;iducuLyHVT@`-8^|Yz>=MrqTN|*Iaj;ZqSV#XZ?{M zwp~AZjK*|Lvf%oDc;YDc#PQtNeX973wi{QHf^vh7R7G?XQwGN{F||M6cMoNf2WwN) z2Q6-Yl$dS@K-io-qsjBZ7@U&#FoddKXha11jBw}MKX4@gs72E@{#oSlRUru zR(X2Dk-70X9zM$Ge2t^p+ z9#HuZ!jD#Im&f6IIa(Q;dU(83xKpIFV%8~X05V(0P>zC`(*H|UK=!Rw z{nuNmYQ3)Nyn?KDMH}${Q1v(BZBEsms_G#$G^*Pg3!{yD*;W4vQK|k}$L$7DTz}#Q zUf4$$ZeP#l+)FCm$cYu^bc4>8VnB}WHoxAUOmqQl_<4OGRfu5McZ0V4c=YZCVeT=I zH<^^pNrW}}XtvEOx(t1}_N^O9?=^i!_n*8vc&Yr+>YIdrzV+mFsds1GOT{&cNnxP6 zLEOs6M_yko;v7-{qs*Wrr-p&LhE}7b7_>=6gMZUG!P&Ob&I8>^1BD|8-3ZZKRd{l7 z;64lY_oHl;LLA9fap%=AQQ;6N<8IsygS!wBZGn(s3R75!3oFKgxN1~I`m+oReDf0i zW%EZ%b1`LZn=Gub%A6E*Iq)^Y3d205Ddcqp0N^t}Pn`ne_w>F%KxppW5eN^Am>k7` zD&mk14v09*2rM;YKB z0M$z-iTv~vE)ZA~)Kn~WmBt7+m{{ewgVN_bjcFwsmpO!;L1dnzSb>iIjL-m%Uc54f zWQ)fR^Q8X6Wds7$!-*XzL$EzpIk2Nb%b3Z*4I1xaVvJ%#M^zMdH*Qas=t@LKK%B#Z zju}Tkpv*UoCd*82FsU*5AxM&oVx`ljdWU&en5;0F!GY_KBa@e=jkC@zNlGPrQsLu_|nl)2(Y_3H_^@V~M-sI$9SJM2_0th` zhgEr>$vTsnQo6-yTXCA@+9G0>Z7eR?>zdc*8jG(Bpm_-fG6m`~_!hvBespx%MFb~Z zRL<~W?J)ulmwtbsp5_7VV_a?n9C*ucQ@B5T|1@B)hVLIjoxka+7@GI+B8>qWRJ@pm zbjwIv<*FNKNndGQf~~bo4uTGQJtu=CNJ2Bf~u;1;ZF5BiJjW13vd|vf?ons^O!7(y-=SJ@fL!N^5y8 z^OSaW(;W8QV`!BGP!7DNrOu!Q 0: + wins.append(True) + else: + wins.append(False) + payoffs.append(env.get_payoffs()[0]) + return json_data, payoffs, wins + +if __name__=='__main__': + game = 'leduc-holdem' + model_ids = ['leduc-holdem-random', 'leduc-holdem-rule-v1', 'leduc-holdem-cfr'] + t = Tournament(game, model_ids) + games_data = t.launch() + print(len(games_data)) + print(games_data[0]) + #root_path = './models' + #agent1 = LeducHoldemDQNModel1(root_path) + #agent2 = LeducHoldemRandomModel(root_path) + #agent3 = LeducHoldemRuleModel() + #agent4 = LeducHoldemCFRModel(root_path) + #agent5 = LeducHoldemDQNModel2(root_path) + #t = Tournament(agent1, agent2, agent3, agent4, agent5, 'leduc-holdem') + ##t.competition() + #t.evaluate() diff --git a/server/tournament/urls.py b/server/tournament/urls.py new file mode 100644 index 0000000..ebd2841 --- /dev/null +++ b/server/tournament/urls.py @@ -0,0 +1,10 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path('replay', views.replay, name='replay'), + path('launch', views.launch, name='launch'), + path('query_payoff', views.query_payoff, name='query_payoff'), + path('query_game', views.query_game, name='query_game'), + ] diff --git a/server/tournament/views.py b/server/tournament/views.py new file mode 100644 index 0000000..cb19633 --- /dev/null +++ b/server/tournament/views.py @@ -0,0 +1,60 @@ +from django.shortcuts import render +from django.http import HttpResponse +from django.db import transaction +from django.core import serializers + +from .models import Game, Payoff + +from .rlcard_wrap import rlcard, MODEL_IDS +from .tournament import Tournament + +def replay(request): + if request.method == 'GET': + name = request.GET['name'] + agent0 = request.GET['agent0'] + agent1 = request.GET['agent1'] + index = request.GET['index'] + g = Game.objects.get(name=name, agent0=agent0, agent1=agent1, index=index) + json_data = g.replay + return HttpResponse(json_data) + +def query_game(request): + if request.method == 'GET': + filter_dict = {key: request.GET.get(key) for key in dict(request.GET).keys()} + result = Game.objects.filter(**filter_dict) + result = serializers.serialize('json', result, fields=('name', 'index', 'agent0', 'agent1', 'win', 'payoff')) + return HttpResponse(result) + +def query_payoff(request): + if request.method == 'GET': + filter_dict = {key: request.GET.get(key) for key in dict(request.GET).keys()} + result = Payoff.objects.filter(**filter_dict) + result = serializers.serialize('json', result) + return HttpResponse(result) + + +@transaction.atomic +def launch(request): + if request.method == 'GET': + eval_num = int(request.GET['eval_num']) + game = request.GET['name'] + games_data, payoffs_data = Tournament(game, MODEL_IDS[game], eval_num).launch() + Game.objects.filter(name=game).delete() + Payoff.objects.filter(name=game).delete() + for game_data in games_data: + g = Game(name=game_data['name'], + index=game_data['index'], + agent0=game_data['agent0'], + agent1=game_data['agent1'], + win=game_data['win'], + payoff=game_data['payoff'], + replay=game_data['replay']) + g.save() + for payoff_data in payoffs_data: + p = Payoff(name=payoff_data['name'], + agent0=payoff_data['agent0'], + agent1=payoff_data['agent1'], + payoff=payoff_data['payoff']) + p.save() + return HttpResponse(1) + diff --git a/server/index.js b/server_bak/index.js similarity index 100% rename from server/index.js rename to server_bak/index.js diff --git a/server/package.json b/server_bak/package.json similarity index 100% rename from server/package.json rename to server_bak/package.json diff --git a/server/sample_data/doudizhu_random.json b/server_bak/sample_data/doudizhu_random.json similarity index 100% rename from server/sample_data/doudizhu_random.json rename to server_bak/sample_data/doudizhu_random.json diff --git a/server/sample_data/sample_doudizhu-test.json b/server_bak/sample_data/sample_doudizhu-test.json similarity index 100% rename from server/sample_data/sample_doudizhu-test.json rename to server_bak/sample_data/sample_doudizhu-test.json diff --git a/server/sample_data/sample_doudizhu.json b/server_bak/sample_data/sample_doudizhu.json similarity index 100% rename from server/sample_data/sample_doudizhu.json rename to server_bak/sample_data/sample_doudizhu.json diff --git a/server/sample_data/sample_leduc_holdem-test.json b/server_bak/sample_data/sample_leduc_holdem-test.json similarity index 100% rename from server/sample_data/sample_leduc_holdem-test.json rename to server_bak/sample_data/sample_leduc_holdem-test.json diff --git a/server/sample_data/sample_leduc_holdem.json b/server_bak/sample_data/sample_leduc_holdem.json similarity index 100% rename from server/sample_data/sample_leduc_holdem.json rename to server_bak/sample_data/sample_leduc_holdem.json