Skip to content

Commit

Permalink
intermediate commit
Browse files Browse the repository at this point in the history
- implemented first version of init func (alg test missing)
  • Loading branch information
liquidiert committed Nov 30, 2020
1 parent d94ab2a commit 1f181ab
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 4 deletions.
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"files.associations": {
"*.tcc": "cpp"
}
},
"python.linting.pylintEnabled": false,
"python.linting.banditEnabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black"
}
72 changes: 70 additions & 2 deletions algorithm_management.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
from fastapi import APIRouter
from fastapi.responses import JSONResponse
from typing import Optional, List
from pydantic import BaseModel, types
from controllers.redis import RedisController as rc
import tempfile
import uuid
import os

router = APIRouter()


class KnownAlg(BaseModel):
name: str
lang: str


class AlgorithmInfo(BaseModel):
name: str
lang: str
Expand All @@ -15,15 +25,73 @@ class AlgorithmInfo(BaseModel):

@router.post("/init", tags=["algorithm"],
response_model=str,
responses={
400: {
"content": {"text/plain": {}},
"description": "Algorithm could not be selected"
},
404: {
"content": {"text/plain": {}},
"description": "Compilation failed"
},
409: {
"content": {"text/plain": {}},
"description": "Compilation failed"
}
},
summary="Inits a new game with either a known algorithm or a completely new one",
description="When a client inits a connection via this call the api will assign an uuid for the client.<br/> \
New algorithms can be submitted as:<br/> \
<ul> \
<li>executable binary &rarr; make example move and add binary to database</li> \
<li>plain code and compile language &rarr; compile code &rarr; make example move and add generated binary to database</li>\
</ul>")
def init(alg_name: Optional[str] = None, new_alg: Optional[AlgorithmInfo] = None):
print(new_alg)
def init(known_alg: Optional[KnownAlg] = None, new_alg: Optional[AlgorithmInfo] = None):
"""
1. see if known_alg is not None
1.1 see if alg really known:
if yes -> generate uuid set it with alg name in redis
if no -> error out telling user to add alg
2. new_alg is not None
2.1. try compilation / injection
if success -> add alg binary; generate uuid and set it with alg name in redis
else -> return compile errors
3. known_alg is None and new_alg is None -> error out
"""
if known_alg is not None:
if not os.path.exists(f"algorithms/{known_alg.lang}/{known_alg.name}"):
return JSONResponse(status_code=400, content="Couldn't find requested algorithm. You may have to create it first.")
else:
client_id = uuid.uuid1()
rc.hset(client_id, known_alg.__dict__)
return client_id
elif new_alg is not None:
if new_alg.executable is not None:
if "py" in new_alg.lang.lower():
with open(f"algorithms/{new_alg.lang}/{new_alg.name}") as executable:
executable.write(new_alg.executable)
else:
with open(f"algorithms/{new_alg.lang}/{new_alg.name}", "wb") as executable:
executable.write(new_alg.executable)
elif new_alg.code is not None:
if "c" in new_alg.lang.lower():
with tempfile.NamedTemporaryFile() as tmpFile:
tmpFile.write(new_alg.code)
os.system(f"g++ {tmpFile.name} -o algorithms/{new_alg.lang}/{new_alg.name}")
elif "py" in new_alg.lang.lower():
with open(f"algorithms/{new_alg.lang}/{new_alg.name}") as out_file:
out_file.write("#!env/bin/python3")
out_file.write(new_alg.code)
else:
return JSONResponse(status_code=404, content="Unknown programming language; couldn't compile algorithm")
else:
return JSONResponse(status_code=400, content="Either executable or plain code must be given")
# TODO: test algs
client_id = uuid.uuid1()
rc.hset(client_id, {"name": new_alg.name, "lang": new_alg.lang})
return client_id
elif:
return JSONResponse(status_code=400, content="Either known_alg or new_alg must be given")


@router.get("/alg_management", response_model=List[str], tags=["algorithm"],
Expand Down
34 changes: 34 additions & 0 deletions controllers/redis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import redis
import hashlib


class RedisController(object):

__instance = None
client: redis.Redis = None

def __new__(cls):
if RedisController.__instance is None:
RedisController.__instance = object.__new__(cls)
RedisController.__instance.client = redis.Redis('localhost', decode_responses=True)
return RedisController.__instance

def get(self, key):
el = RedisController.__instance.client.get(key)
return el if el is not None else ""

def set(self, key, data):
return RedisController.__instance.client.set(key, data)

def hget(self, key):
el = RedisController.__instance.client.hget(key)
return el if el is not None else ""

def hset(self, key, data: dict):
return RedisController.__instance.client.hset(key, data)

def lpush(self, key, data):
return RedisController.__instance.client.lpush(key, data)

def lrange(self, key, start=0, end=-1):
return RedisController.__instance.client.lrange(key, start, end)
3 changes: 2 additions & 1 deletion game_management.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from fastapi import APIRouter
from pydantic import BaseModel
from typing import List, Tuple
from fastapi.responses import ORJSONResponse
from uuid import UUID

router = APIRouter()
Expand All @@ -23,7 +24,7 @@ class MoveInfo(BaseModel):
tile_map: List[List[int]]


@router.post("/move", response_model=Tuple[int], tags=["game"],
@router.post("/move", response_class=ORJSONResponse, response_model=Tuple[int], tags=["game"],
summary="Get future velocity for opponent AI from current game situation")
def move(info: MoveInfo):
pass
Expand Down
13 changes: 13 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from algorithm_management import router as alg_router
from game_management import router as game_router

Expand All @@ -7,5 +8,17 @@
description="Algorithm database and ai game handler for pactheman",
version="0.0.1"
)

@app.get("/", response_class=HTMLResponse, include_in_schema=False)
def hello_world():
return """
<html>
<body>
Hi there and very welcome to the pactheman api!<br/>
If you are here for the docs see <a href='/docs'>OpenAPI</a> or <a href='/redoc'>redoc</a>.
</body>
</html>
"""

app.include_router(alg_router)
app.include_router(game_router)

0 comments on commit 1f181ab

Please sign in to comment.