Als Alternative zur Web-IDE kann man auch einen externen Editor verwenden und den code per REST-API hochladen. Leider gibt es hier noch einen Bug mit einem CSRF token. Als Workaround kann hierfür folgendes (etwas frickeliges) Python-Script verwendet werden, was sich genauso wie der Browser verhält. Hierfür muss man sich zunächst mit einem Browser einloggen und die session und parent id in die **config**-Datei eintragen, die im gleichen Verzeichnis wie das Pythonscript liegen muss. Der eigentliche Quellcode, den man normalerweise in die Web-IDE eintippt, muss im gleichen Verzeichnis in der **bot.cpp** vorliegen. upload.py muss nur einmalig gestartet werden und läuft dann im Hintergrund. Immer dann wenn man die bot.cpp speichert, wird der aktuelle Stand automatisch hochgeladen.
upload.py:
#!/usr/bin/env python3 import os import json import requests from bs4 import BeautifulSoup from colorama import Fore from colorama import Style def upload(): config = json.load(open('config')) get_url = 'https://schlangen.bytewerk.org/snake/edit/latest' cookies = {'sessionid': config['session_id']} r = requests.get(get_url, cookies=cookies) cookies['csrftoken'] = r.cookies['csrftoken'] soup = BeautifulSoup(r.text, 'lxml') xcsrf = soup.select_one('input[name="csrfmiddlewaretoken"]')['value'] code = open('bot.cpp').read() post_url = 'https://schlangen.bytewerk.org/snake/edit/save' form_data = {'action': 'run', 'code': code, 'comment': None, 'parent': config['snake_id']} r = requests.post(post_url, headers={'X-CSRFToken': xcsrf, 'X-Requested-With': 'XMLHttpRequest'}, json=form_data, cookies=cookies) print(r.text) print('waiting for compilation...') state = 'not_compiled' while state == 'not_compiled': r = requests.get('https://schlangen.bytewerk.org/api/v1/compile_state', cookies=cookies) j = json.loads(r.text) state = j['compile_state'] for l in j['build_log']: fmt = f'{Fore.GREEN}' if not 'e' in l.keys() else f'{Fore.RED}' fmt_reset = f'{Style.RESET_ALL}' key = list(l.keys())[0] print('%s%s%s' % (fmt, l[key], fmt_reset), end='') while True: try: os.system('inotifywait -e modify bot.cpp') upload() except KeyboardInterrupt: break
config:
{ "session_id": "xxx", "snake_id": 1234 }
bot.cpp:
// You can use the entire C/C++ standard library, just add the relevant // #includes. We recommend math.h ;-) #include "usercode.h" /* * This is your bot's startup function. Here you can set your snake's colors, * set up persistent variables, etc. */ bool init(Api *api) { // remove the default color api->clearColors(); // I'm green! api->addColor(40, 255, 0); api->addColor(20, 128, 0); api->addColor(10, 64, 0); api->addColor(20, 128, 0); // indicate successful startup. If anything goes wrong, // return false and we'll clean you up. return true; } /* * This function will be called by the framework on every step. Here you decide * where to move next! * * Use the provided Api object to interact with the world and make sure you set * the following outputs: * * - api->angle: Set your relative movement angle * - api->boost: Set this to true to move faster, but you will loose mass. * * The Api object also provides information about the world around you. See the * documentation for more details. */ bool step(Api *api) { // let's start by moving in a large circle. Please note that all angles are // represented in radians, where -π to +π is a full circle. api->angle = 0.001; // check for other snakes for(size_t i = 0; i < api->getSegmentCount(); i++) { const IpcSegmentInfo &seg = api->getSegments()[i]; if(!seg.is_self && seg.dist < 20) { // you can send log messages to your browser or any other viewer with the // appropriate Viewer Key. api->log("Oh no, I'm going to die!"); break; } } // finding food is quite similar // Signal that everything is ok. Return false here if anything goes wrong but // you want to shut down cleanly. return true; }