def presetWebService(self): # web service to get the content of the preset file if self.vars.preset == None: raiseHttp(400, "Missing parameter preset") preset = self.vars.preset if IS_ALPHANUMERIC()(preset)[1] is not None: raiseHttp(400, "Preset name must be alphanumeric") if IS_LENGTH(maxsize=32, minsize=1)(preset)[1] is not None: raiseHttp(400, "Preset name must be between 1 and 32 characters") print("presetWebService: preset={}".format(preset)) fullPath = '{}/{}.json'.format(getPresetDir(preset), preset) # check that the presets file exists if os.path.isfile(fullPath): # load it try: params = PresetLoader.factory(fullPath).params except Exception as e: raiseHttp(400, "Can't load the preset") params = json.dumps(params) return params else: raiseHttp(400, "Preset not found")
def loadPreset(self): # load conf from session if available loaded = False if self.vars.action is not None: # press solve, load or save button if self.vars.action in ['Update', 'Create']: # store the changes in case the form won't be accepted presetDict = self.genJsonFromParams(self.vars) self.session.presets['presetDict'] = presetDict params = PresetLoader.factory(presetDict).params loaded = True elif self.vars.action in ['Load']: # nothing to load, we'll load the new params file with the load form code pass else: # no forms button pressed if self.session.presets['presetDict'] is not None: params = PresetLoader.factory( self.session.presets['presetDict']).params loaded = True if not loaded: presetPath = '{}/{}.json'.format( getPresetDir(self.session.presets['preset']), self.session.presets['preset']) params = PresetLoader.factory(presetPath).params return params
def getSkillLevelBarData(self, preset): result = {'name': preset} try: params = PresetLoader.factory('{}/{}.json'.format( getPresetDir(preset), preset)).params result['custom'] = (preset, params['score']) # add stats on the preset result['knowsKnown'] = len([ know for know in params['Knows'] if params['Knows'][know][0] == True ]) except: result['custom'] = (preset, 'N/A') result['knowsKnown'] = 'N/A' # get score of standard presets standardScores = self.cache.ram('standardScores', lambda: dict(), time_expire=None) if not standardScores: for preset in [ 'newbie', 'casual', 'regular', 'veteran', 'expert', 'master', 'samus' ]: score = PresetLoader.factory('{}/{}.json'.format( getPresetDir(preset), preset)).params['score'] standardScores[preset] = score result['standards'] = standardScores with DB() as db: result['lastAction'] = db.getPresetLastActionDate( result['custom'][0]) # TODO: normalize result (or not ?) return result
def computeDifficulty(self, jsonRomFileName, preset): randomizedRom = os.path.basename(jsonRomFileName.replace( 'json', 'sfc')) presetFileName = "{}/{}.json".format(getPresetDir(preset), preset) (fd, jsonFileName) = tempfile.mkstemp() db = DB() id = db.initSolver() params = [ getPythonExec(), os.path.expanduser("~/RandomMetroidSolver/solver.py"), '-r', str(jsonRomFileName), '--preset', presetFileName, '--difficultyTarget', str(self.session.solver['difficultyTarget']), '--pickupStrategy', self.session.solver['pickupStrategy'], '--type', 'web', '--output', jsonFileName, '--runtime', '10' ] for item in self.session.solver['itemsForbidden']: params += ['--itemsForbidden', item] db.addSolverParams(id, randomizedRom, preset, self.session.solver['difficultyTarget'], self.session.solver['pickupStrategy'], self.session.solver['itemsForbidden']) print("before calling solver: {}".format(params)) start = datetime.now() ret = subprocess.call(params) end = datetime.now() duration = (end - start).total_seconds() print("ret: {}, duration: {}s".format(ret, duration)) if ret == 0: with open(jsonFileName) as jsonFile: result = json.load(jsonFile) else: result = "Solver: something wrong happened while solving the ROM" db.addSolverResult(id, ret, duration, result) db.close() os.close(fd) os.remove(jsonFileName) return (ret == 0, result)
def skillPresetActionWebService(self): print("skillPresetActionWebService call") if self.session.presets is None: self.session.presets = {} # for create/update, not load (ok, msg) = self.validatePresetsParams(self.vars.action) if not ok: raiseHttp(400, json.dumps(msg)) else: self.session.presets['currentTab'] = self.vars.currenttab if self.vars.action == 'Create': preset = self.vars.presetCreate else: preset = self.vars.preset # check if the presets file already exists password = self.vars['password'] password = password.encode('utf-8') passwordSHA256 = hashlib.sha256(password).hexdigest() fullPath = '{}/{}.json'.format(getPresetDir(preset), preset) if os.path.isfile(fullPath): # load it end = False try: oldParams = PresetLoader.factory(fullPath).params except Exception as e: msg = "UC:Error loading the preset {}: {}".format(preset, e) end = True if end == True: raiseHttp(400, json.dumps(msg)) # check if password match if 'password' in oldParams and passwordSHA256 == oldParams[ 'password']: # update the presets file paramsDict = self.genJsonFromParams(self.vars) paramsDict['password'] = passwordSHA256 try: PresetLoader.factory(paramsDict).dump(fullPath) with DB() as db: db.addPresetAction(preset, 'update') self.updatePresetsSession() msg = "Preset {} updated".format(preset) return json.dumps(msg) except Exception as e: msg = "Error writing the preset {}: {}".format(preset, e) raiseHttp(400, json.dumps(msg)) else: msg = "Password mismatch with existing presets file {}".format( preset) raiseHttp(400, json.dumps(msg)) else: # prevent a malicious user from creating presets in a loop if not self.maxPresetsReach(): # write the presets file paramsDict = self.genJsonFromParams(self.vars) paramsDict['password'] = passwordSHA256 try: PresetLoader.factory(paramsDict).dump(fullPath) with DB() as db: db.addPresetAction(preset, 'create') self.updatePresetsSession() # add new preset in cache (stdPresets, tourPresets, comPresets) = loadPresetsList(self.cache) comPresets.append(preset) comPresets.sort(key=lambda v: v.upper()) msg = "Preset {} created".format(preset) return json.dumps(msg) except Exception as e: msg = "Error writing the preset {}: {}".format(preset, e) raiseHttp(400, json.dumps(msg)) redirect(URL(r=request, f='presets')) else: msg = "Sorry, maximum number of presets reached, can't add more" raiseHttp(400, json.dumps(msg))
def run(self): self.initPresetsSession() # use web2py builtin cache to avoid recomputing the hardrooms requirements hardRooms = self.cache.ram('hardRooms', lambda: dict(), time_expire=None) if len(hardRooms) == 0: self.computeHardRooms(hardRooms) hellRuns = self.cache.ram('hellRuns', lambda: dict(), time_expire=None) if len(hellRuns) == 0: self.computeHellruns(hellRuns) if self.vars.action is not None: (ok, msg) = self.validatePresetsParams(self.vars.action) if not ok: self.session.flash = msg redirect(URL(r=self.request, f='presets')) else: self.session.presets['currentTab'] = self.vars.currenttab preset = self.vars.preset # in web2py.js, in disableElement, remove 'working...' to have action with correct value if self.vars.action == 'Load': # check that the presets file exists fullPath = '{}/{}.json'.format(getPresetDir(preset), preset) if os.path.isfile(fullPath): # load it try: params = PresetLoader.factory(fullPath).params self.updatePresetsSession() self.session.presets["presetDict"] = None except Exception as e: self.session.flash = "L:Error loading the preset {}: {}".format( preset, e) else: self.session.flash = "Presets file not found: {}".format( fullPath) redirect(URL(r=self.request, f='presets')) # load conf from session if available error = False try: params = self.loadPreset() except Exception as e: self.session.presets['preset'] = 'regular' self.session.flash = "S:Error loading the preset: {}".format(e) error = True if error == True: redirect(URL(r=request, f='presets')) # load presets list (stdPresets, tourPresets, comPresets) = loadPresetsList(self.cache) # add missing knows/settings completePreset(params) # compute score for skill bar skillBarData = self.getSkillLevelBarData( self.session.presets['preset']) # send values to view return dict(desc=Knows.desc, difficulties=diff2text, categories=Knows.categories, settings=params['Settings'], knows=params['Knows'], easy=easy, medium=medium, hard=hard, harder=harder, hardcore=hardcore, mania=mania, controller=params['Controller'], stdPresets=stdPresets, tourPresets=tourPresets, comPresets=comPresets, skillBarData=skillBarData, hardRooms=hardRooms, hellRuns=hellRuns)
okValues = [value] if altValue is not None: okValues.append(altValue) if argDict[arg] not in okValues: argDict[arg] = value forcedArgs[webArg if webArg != None else arg] = webValue if webValue != None else value print(msg) optErrMsgs.append(msg) # if rando preset given, load it first if args.randoPreset != None: preset = loadRandoPreset(args.randoPreset, args) # use the skill preset from the rando preset if preset is not None and args.paramsFileName is None: args.paramsFileName = '{}/{}/{}.json'.format(appDir, getPresetDir(preset), preset) # if diff preset given, load it if args.paramsFileName is not None: PresetLoader.factory(args.paramsFileName).load() preset = os.path.splitext(os.path.basename(args.paramsFileName))[0] if args.preset is not None: preset = args.preset else: preset = 'default' logger.debug("preset: {}".format(preset)) # if no seed given, choose one if args.seed == 0:
okValues.append(altValue) if argDict[arg] not in okValues: argDict[arg] = value forcedArgs[webArg if webArg != None else arg] = webValue if webValue != None else value print(msg) optErrMsgs.append(msg) # if rando preset given, load it first if args.randoPreset != None: preset = loadRandoPreset(args.randoPreset, args) # use the skill preset from the rando preset if preset is not None and args.paramsFileName is None: args.paramsFileName = '{}/{}/{}.json'.format( appDir, getPresetDir(preset), preset) # if diff preset given, load it if args.paramsFileName is not None: PresetLoader.factory(args.paramsFileName).load() preset = os.path.splitext(os.path.basename(args.paramsFileName))[0] if args.preset is not None: preset = args.preset else: preset = 'default' logger.debug("preset: {}".format(preset)) # if no seed given, choose one if args.seed == 0:
def validateSolverParams(self): for param in ['difficultyTarget', 'pickupStrategy', 'complexity']: if self.vars[param] is None: return (False, "Missing parameter {}".format(param)) if self.vars.preset == None: return (False, "Missing parameter preset") preset = self.vars.preset if IS_ALPHANUMERIC()(preset)[1] is not None: return (False, "Wrong value for preset, must be alphanumeric") if IS_LENGTH(maxsize=32, minsize=1)(preset)[1] is not None: return ( False, "Wrong length for preset, name must be between 1 and 32 characters" ) # check that preset exists fullPath = '{}/{}.json'.format(getPresetDir(preset), preset) if not os.path.isfile(fullPath): return (False, "Unknown preset: {}".format(preset)) difficultyTargetChoices = [ "easy", "medium", "hard", "very hard", "hardcore", "mania" ] if self.vars.difficultyTarget not in difficultyTargetChoices: return ( False, "Wrong value for difficultyTarget: {}, authorized values: {}". format(self.vars.difficultyTarget, difficultyTargetChoices)) pickupStrategyChoices = ["all", "any"] if self.vars.pickupStrategy not in pickupStrategyChoices: return (False, "Wrong value for pickupStrategy: {}, authorized values: {}" .format(self.vars.pickupStrategy, pickupStrategyChoice)) complexityChoices = ["simple", "advanced"] if self.vars.complexity not in complexityChoices: return ( False, "Wrong value for complexity: {}, authorized values: {}".format( self.vars.complexity, complexityChoices)) itemsForbidden = [] for item in [ 'ETank', 'Missile', 'Super', 'PowerBomb', 'Bomb', 'Charge', 'Ice', 'HiJump', 'SpeedBooster', 'Wave', 'Spazer', 'SpringBall', 'Varia', 'Plasma', 'Grapple', 'Morph', 'Reserve', 'Gravity', 'XRayScope', 'SpaceJump', 'ScrewAttack' ]: boolvar = self.vars[item + "_bool"] if boolvar is not None: if boolvar != 'on': return (False, "Wrong value for {}: {}, authorized values: on/off" .format(item, boolvar)) if self.vars.romJson is None and self.vars.uploadFile is None and self.vars.romFile is None: return (False, "Missing ROM to solve") if self.vars.romFile is not None: if IS_LENGTH(maxsize=255, minsize=1)(self.vars.romFile)[1] is not None: return ( False, "Wrong length for romFile, name must be between 1 and 256 characters: {}" .format(request.vars.romFile)) if self.vars.romJson is not None and len(self.vars.romJson) > 0: try: json.loads(self.vars.romJson) except: return (False, "Wrong value for romJson, must be a JSON string: [{}]". format(self.vars.romJson)) if self.vars.uploadFile is not None: if type(self.vars.uploadFile) == str: if IS_MATCH('[a-zA-Z0-9_\.() ,\-]*', strict=True)( request.vars.uploadFile)[1] is not None: return ( False, "Wrong value for uploadFile, must be a valid file name: {}" .format(self.vars.uploadFile)) if IS_LENGTH(maxsize=256, minsize=1)(self.vars.uploadFile)[1] is not None: return ( False, "Wrong length for uploadFile, name must be between 1 and 255 characters" ) return (True, None)
def customWebService(self): print("customWebService") # check validity of all parameters switchs = [ 'itemsounds', 'spinjumprestart', 'rando_speed', 'elevators_speed', 'fast_doors', 'AimAnyButton', 'max_ammo_display', 'supermetroid_msu1', 'Infinite_Space_Jump', 'refill_before_save', 'customSpriteEnable', 'customItemsEnable', 'noSpinAttack', 'customShipEnable', 'remove_itemsounds', 'remove_elevators_speed', 'remove_fast_doors', 'remove_Infinite_Space_Jump', 'remove_rando_speed', 'remove_spinjumprestart', 'gamepadMapping', 'widescreen', 'hell', 'lava_acid_physics' ] others = [ 'colorsRandomization', 'suitsPalettes', 'beamsPalettes', 'tilesPalettes', 'enemiesPalettes', 'bossesPalettes', 'minDegree', 'maxDegree', 'invert', 'hellrun_rate', 'etanks' ] validateWebServiceParams(self.request, switchs, [], [], others, isJson=True) if self.vars.customSpriteEnable == 'on': if self.vars.customSprite == 'random': for sprite in self.vars.customSpriteMultiSelect.split(','): if sprite not in customSprites: raiseHttp(400, "Wrong value for customSpriteMultiSelect", True) elif self.vars.customSprite not in customSprites: raiseHttp(400, "Wrong value for customSprite", True) if self.vars.customShipEnable == 'on': if self.vars.customShip == 'random': for ship in self.vars.customShipMultiSelect.split(','): if ship not in customShips: raiseHttp(400, "Wrong value for customShipMultiSelect", True) elif self.vars.customShip not in customShips: raiseHttp(400, "Wrong value for customShip", True) if self.vars.music not in [ "Don't touch", "Disable", "Randomize", "Customize", "Restore" ]: raiseHttp(400, "Wrong value for music", True) if self.session.customizer == None: self.session.customizer = {} # update session self.session.customizer[ 'colorsRandomization'] = self.vars.colorsRandomization self.session.customizer['suitsPalettes'] = self.vars.suitsPalettes self.session.customizer['beamsPalettes'] = self.vars.beamsPalettes self.session.customizer['tilesPalettes'] = self.vars.tilesPalettes self.session.customizer['enemiesPalettes'] = self.vars.enemiesPalettes self.session.customizer['bossesPalettes'] = self.vars.bossesPalettes self.session.customizer['minDegree'] = self.vars.minDegree self.session.customizer['maxDegree'] = self.vars.maxDegree self.session.customizer['invert'] = self.vars.invert self.session.customizer['globalShift'] = self.vars.globalShift self.session.customizer[ 'customSpriteEnable'] = self.vars.customSpriteEnable self.session.customizer['customSprite'] = self.vars.customSprite if self.vars.customSprite == 'random': self.session.customizer[ 'customSpriteMultiSelect'] = self.vars.customSpriteMultiSelect.split( ',') self.session.customizer[ 'customItemsEnable'] = self.vars.customItemsEnable self.session.customizer['noSpinAttack'] = self.vars.noSpinAttack self.session.customizer[ 'customShipEnable'] = self.vars.customShipEnable self.session.customizer['customShip'] = self.vars.customShip if self.vars.customShip == 'random': self.session.customizer[ 'customShipMultiSelect'] = self.vars.customShipMultiSelect.split( ',') self.session.customizer['gamepadMapping'] = self.vars.gamepadMapping if self.session.customizer['gamepadMapping'] == "on": self.session.customizer['preset'] = self.vars.preset self.session.customizer['itemsounds'] = self.vars.itemsounds self.session.customizer['spinjumprestart'] = self.vars.spinjumprestart self.session.customizer['rando_speed'] = self.vars.rando_speed self.session.customizer['elevators_speed'] = self.vars.elevators_speed self.session.customizer['fast_doors'] = self.vars.fast_doors self.session.customizer[ 'Infinite_Space_Jump'] = self.vars.Infinite_Space_Jump self.session.customizer[ 'refill_before_save'] = self.vars.refill_before_save self.session.customizer['widescreen'] = self.vars.widescreen self.session.customizer['AimAnyButton'] = self.vars.AimAnyButton self.session.customizer[ 'max_ammo_display'] = self.vars.max_ammo_display self.session.customizer[ 'supermetroid_msu1'] = self.vars.supermetroid_msu1 self.session.customizer[ 'remove_itemsounds'] = self.vars.remove_itemsounds self.session.customizer[ 'remove_elevators_speed'] = self.vars.remove_elevators_speed self.session.customizer[ 'remove_fast_doors'] = self.vars.remove_fast_doors self.session.customizer[ 'remove_spinjumprestart'] = self.vars.remove_spinjumprestart self.session.customizer[ 'remove_Infinite_Space_Jump'] = self.vars.remove_Infinite_Space_Jump self.session.customizer[ 'remove_rando_speed'] = self.vars.remove_rando_speed self.session.customizer[ 'lava_acid_physics'] = self.vars.lava_acid_physics self.session.customizer['hell'] = self.vars.hell self.session.customizer['hellrun_rate'] = self.vars.hellrun_rate self.session.customizer['etanks'] = self.vars.etanks self.session.customizer['music'] = self.vars.music if self.vars.music == 'Customize': musics = self.loadMusics() for song, songId in musics["_list"]: self.session.customizer[songId] = self.vars[songId] # when beam doors patch is detected, don't randomize blue door palette no_blue_door_palette = self.vars.no_blue_door_palette # call the randomizer (fd, jsonFileName) = tempfile.mkstemp() params = [ getPythonExec(), os.path.expanduser("~/RandomMetroidSolver/randomizer.py"), '--output', jsonFileName, '--patchOnly' ] if self.vars.itemsounds == 'on': params += ['-c', 'itemsounds.ips'] if self.vars.elevators_speed == 'on': params += ['-c', 'elevators_speed.ips'] if self.vars.fast_doors == 'on': params += ['-c', 'fast_doors.ips'] if self.vars.spinjumprestart == 'on': params += ['-c', 'spinjumprestart.ips'] if self.vars.rando_speed == 'on': params += ['-c', 'rando_speed.ips'] if self.vars.AimAnyButton == 'on': params += ['-c', 'AimAnyButton.ips'] if self.vars.max_ammo_display == 'on': params += ['-c', 'max_ammo_display.ips'] if self.vars.supermetroid_msu1 == 'on': params += ['-c', 'supermetroid_msu1.ips'] if self.vars.Infinite_Space_Jump == 'on': params += ['-c', 'Infinite_Space_Jump'] if self.vars.refill_before_save == 'on': params += ['-c', 'refill_before_save.ips'] if self.vars.widescreen == 'on': params += ['-c', 'widescreen.ips'] if self.vars.remove_itemsounds == 'on': params += ['-c', 'remove_itemsounds.ips'] if self.vars.remove_elevators_speed == 'on': params += ['-c', 'remove_elevators_speed.ips'] if self.vars.remove_fast_doors == 'on': params += ['-c', 'remove_fast_doors.ips'] if self.vars.remove_rando_speed == 'on': params += ['-c', 'remove_rando_speed.ips'] if self.vars.remove_spinjumprestart == 'on': params += ['-c', 'remove_spinjumprestart.ips'] if self.vars.remove_Infinite_Space_Jump == 'on': params += ['-c', 'remove_Infinite_Space_Jump.ips'] if self.vars.music == 'Disable': params += ['-c', 'No_Music'] if self.vars.music == 'Randomize': params += ['-c', 'random_music.ips'] if self.vars.music == 'Restore': params += ['-c', 'vanilla_music.ips'] if self.vars.lava_acid_physics == 'on': params += ['-c', 'lava_acid_physics.ips'] if self.vars.hell == 'on': params += ['-c', 'hell.ips'] if self.vars.hellrun_rate != 'off': params += ['--hellrun', self.vars.hellrun_rate] if self.vars.etanks != 'off': params += ['--etanks', self.vars.etanks] if self.vars.colorsRandomization == 'on': params.append('--palette') if self.vars.suitsPalettes == 'off': params.append('--no_shift_suit_palettes') if self.vars.beamsPalettes == 'off': params.append('--no_shift_beam_palettes') if self.vars.tilesPalettes == 'off': params.append('--no_shift_tileset_palette') if self.vars.enemiesPalettes == 'off': params.append('--no_shift_enemy_palettes') if self.vars.bossesPalettes == 'off': params.append('--no_shift_boss_palettes') if self.vars.globalShift == 'off': params.append('--no_global_shift') params.append('--individual_suit_shift') params.append('--individual_tileset_shift') params.append('--no_match_ship_and_power') params += [ '--min_degree', self.vars.minDegree, '--max_degree', self.vars.maxDegree ] if self.vars.invert == 'on': params.append('--invert') if no_blue_door_palette == 'on': params.append('--no_blue_door_palette') if self.vars.customSpriteEnable == 'on': if self.vars.customSprite == 'random': sprite = random.choice( self.session.customizer['customSpriteMultiSelect']) else: sprite = self.vars.customSprite params += ['--sprite', "{}.ips".format(sprite)] with DB() as db: db.addSprite(sprite) if self.vars.customItemsEnable == 'on': params.append('--customItemNames') if self.vars.noSpinAttack == 'on': params.append('--no_spin_attack') if self.vars.customShipEnable == 'on': if self.vars.customShip == 'random': ship = random.choice( self.session.customizer['customShipMultiSelect']) else: ship = self.vars.customShip params += ['--ship', "{}.ips".format(ship)] with DB() as db: db.addShip(ship) if customShips[ship].get("hideSamus", False): params += ['-c', 'custom_ship.ips'] if customShips[ship].get("showSamusAtTakeoff", False): params += ['-c', 'Ship_Takeoff_Disable_Hide_Samus'] if self.vars.seedKey != None: with DB() as db: seedIpsInfo = db.getSeedIpsInfo(self.vars.seedKey) print("seedIpsInfo: {}".format(seedIpsInfo)) if seedIpsInfo == None or len(seedIpsInfo) == 0: raiseHttp(400, json.dumps("Can't get seed info")) (uploadStatus, fileName) = seedIpsInfo[0] if uploadStatus not in ['local', 'pending', 'uploaded']: raiseHttp(400, json.dumps("Seed is not available")) ipsFileName = os.path.join(localIpsDir, self.vars.seedKey, fileName.replace('sfc', 'ips')) params += ['--seedIps', ipsFileName] if self.vars.music == "Customize": musics = self.loadMusics() customMusic = { 'params': { "varia": self.vars.varia == "true", "area": self.vars.area == "true", "boss": self.vars.boss == "true" }, 'mapping': {} } for song, songId in musics["_list"]: newSong = self.vars[songId] if newSong not in musics: raiseHttp(400, "unknown song for {}".format(song)) if newSong != song: customMusic['mapping'][song] = newSong (fd2, jsonMusicFileName) = tempfile.mkstemp() with open(jsonMusicFileName, 'w') as musicFile: json.dump(customMusic, musicFile) params += ['--music', jsonMusicFileName] if self.vars.gamepadMapping == "on": preset = self.vars.preset fullPath = '{}/{}.json'.format(getPresetDir(preset), preset) controlMapping = PresetLoader.factory( fullPath).params['Controller'] (custom, controlParam) = getCustomMapping(controlMapping) if custom == True: print("apply custom gamepad mapping from preset: {}".format( self.vars.preset)) params += ['--controls', controlParam] if "Moonwalk" in controlMapping and controlMapping[ "Moonwalk"] == True: params.append('--moonwalk') print("before calling: {}".format(params)) start = datetime.now() ret = subprocess.call(params) end = datetime.now() duration = (end - start).total_seconds() print("ret: {}, duration: {}s".format(ret, duration)) if self.vars.music == "Customize": os.close(fd2) os.remove(jsonMusicFileName) if ret == 0: with open(jsonFileName) as jsonFile: data = json.load(jsonFile) os.close(fd) os.remove(jsonFileName) return json.dumps(data) else: # extract error from json try: with open(jsonFileName) as jsonFile: msg = json.load(jsonFile)['errorMsg'] except: msg = "customizerWebService: something wrong happened" os.close(fd) os.remove(jsonFileName) raiseHttp(400, json.dumps(msg))
def validateWebServiceParams(request, switchs, quantities, multis, others, isJson=False): parameters = switchs + quantities + multis + others for param in parameters: if request.vars[param] is None: raiseHttp(400, "Missing parameter: {}".format(param), isJson) # switchs for switch in switchs: if request.vars[switch] not in ['on', 'off', 'random']: raiseHttp( 400, "Wrong value for {}, authorized values: on/off".format(switch), isJson) # quantities for qty in quantities: if request.vars[qty] == 'random': continue if qty == 'minimizerQty': if request.vars.minimizer == 'on': qtyInt = getInt(request, qty, isJson) if qtyInt < 30 or qtyInt > 100: raiseHttp( 400, "Wrong value for {}, must be between 30 and 100". format(qty), isJson) elif qty == 'scavNumLocs': if request.vars.majorsSplit == 'Scavenger': qtyInt = getInt(request, qty, isJson) if qtyInt < 4 or qtyInt > 17: raiseHttp( 400, "Wrong value for {}, must be between 4 and 16".format( qty), isJson) else: qtyFloat = getFloat(request, qty, isJson) if qtyFloat < 1.0 or qtyFloat > 9.0: raiseHttp( 400, "Wrong value for {}, must be between 1 and 9".format(qty), isJson) # multis defaultMultiValues = getDefaultMultiValues() for param in multis: paramMulti = param + "MultiSelect" value = request.vars[param] if value == 'random': if request.vars[paramMulti] is not None: # get multi values for value in request.vars[paramMulti].split(','): # check multi values if value not in defaultMultiValues[param]: raiseHttp( 400, "Wrong value for {}, authorized values: {}".format( param, defaultMultiValues[param]), isJson) else: # check value if value not in defaultMultiValues[param]: raiseHttp( 400, "Wrong value for {}, authorized values: {}".format( param, defaultMultiValues[param]), isJson) # others if request.vars.minorQty not in ['random', None]: minorQtyInt = getInt(request, 'minorQty', isJson) if minorQtyInt < 7 or minorQtyInt > 100: raiseHttp(400, "Wrong value for minorQty, must be between 7 and 100", isJson) if 'gravityBehaviour' in others: if request.vars.gravityBehaviour not in [ 'Balanced', 'Progressive', 'Vanilla' ]: raiseHttp(400, "Wrong value for gravityBehaviour", isJson) if 'complexity' in others: if request.vars['complexity'] not in ['simple', 'medium', 'advanced']: raiseHttp( 400, "Wrong value for complexity, authorized values simple/medium/advanced", isJson) if 'paramsFileTarget' in others: try: json.loads(request.vars.paramsFileTarget) except: raiseHttp( 400, "Wrong value for paramsFileTarget, must be a JSON string", isJson) if 'seed' in others: seedInt = getInt(request, 'seed', isJson) if seedInt < 0 or seedInt > sys.maxsize: raiseHttp(400, "Wrong value for seed", isJson) if 'objective' in others: objective = request.vars.objective.split(',') authorizedObjectives = defaultMultiValues['objective'] + [ 'random', 'nothing' ] for value in objective: if value not in authorizedObjectives: raiseHttp(400, "Wrong value for objective", isJson) if objective == ['random']: for value in request.vars.objectiveMultiSelect.split(','): if value not in authorizedObjectives: raiseHttp(400, "Wrong value for objectiveMultiSelect", isJson) if 'tourian' in others: if request.vars['tourian'] not in ['Vanilla', 'Fast', 'Disabled']: raiseHttp( 400, "Wrong value fro tourian, authorized values: Vanilla/Fast/Disabled", isJson) if 'hellrun_rate' in others and request.vars.hellrun_rate != 'off': hellrun_rate = getInt(request, 'hellrun_rate', isJson) if hellrun_rate < 0 or hellrun_rate > 400: raiseHttp(400, "Wrong value for hellrun_rate", isJson) if 'etanks' in others and request.vars.etanks != 'off': etanks = getInt(request, 'etanks', isJson) if etanks < 0 or etanks > 14: raiseHttp(400, "Wrong value for etanks", isJson) preset = request.vars.preset if preset != None: if IS_ALPHANUMERIC()(preset)[1] is not None: raiseHttp(400, "Wrong value for preset, must be alphanumeric", isJson) if IS_LENGTH(maxsize=32, minsize=1)(preset)[1] is not None: raiseHttp( 400, "Wrong length for preset, name must be between 1 and 32 characters", isJson) # check that preset exists fullPath = '{}/{}.json'.format(getPresetDir(preset), preset) if not os.path.isfile(fullPath): raiseHttp(400, "Unknown preset", isJson) randoPreset = request.vars.randoPreset if randoPreset != None and len(randoPreset) > 0: if IS_ALPHANUMERIC()(randoPreset)[1] is not None: raiseHttp(400, "Wrong value for randoPreset, must be alphanumeric", isJson) if IS_LENGTH(maxsize=32, minsize=1)(randoPreset)[1] is not None: raiseHttp( 400, "Wrong length for randoPreset, name must be between 1 and 32 characters", isJson) # check that randoPreset exists fullPath = 'rando_presets/{}.json'.format(randoPreset) if not os.path.isfile(fullPath): raiseHttp(400, "Unknown randoPreset", isJson) # check race mode if 'raceMode' in request.vars: if request.vars.raceMode not in ['on', 'off']: raiseHttp(400, "Wrong value for race mode, must on/off", isJson) # check seed key if 'seedKey' in request.vars: if IS_MATCH('^[0-9a-z-]*$')(request.vars.seedKey)[1] is not None: raiseHttp(400, "Seed key can only contain [0-9a-z-]", isJson) if IS_LENGTH(maxsize=36, minsize=36)(request.vars.seedKey)[1] is not None: raiseHttp(400, "Seed key must be 36 chars long", isJson)
def run(self): self.initExtStatsSession() if self.vars.action == 'Load': (ok, msg) = self.validateExtStatsParams() if not ok: self.session.flash = msg redirect(URL(r=self.request, f='extStats')) self.updateExtStatsSession() skillPreset = self.vars.preset randoPreset = self.vars.randoPreset # load rando preset to get majors split fullPath = 'rando_presets/{}.json'.format(randoPreset) if not os.path.isfile(fullPath): raiseHttp(400, "Unknown rando preset: {}".format(e)) try: with open(fullPath) as jsonFile: randoPresetContent = json.load(jsonFile) except Exception as e: raiseHttp(400, "Can't load the rando preset: {}".format(e)) majorsSplit = randoPresetContent["majorsSplit"] # load skill preset fullPath = '{}/{}.json'.format(getPresetDir(skillPreset), skillPreset) try: skillPresetContent = PresetLoader.factory(fullPath).params completePreset(skillPresetContent) except Exception as e: raiseHttp(400, "Error loading the skill preset: {}".format(e)) with DB() as db: (itemsStats, techniquesStats, difficulties, solverStatsRaw) = db.getExtStat(skillPreset, randoPreset) solverStats = {} if "avgLocs" in solverStatsRaw: solverStats["avgLocs"] = transformStats( solverStatsRaw["avgLocs"]) solverStats["avgLocs"].insert( 0, ['Available locations', 'Percentage']) if "open14" in solverStatsRaw: open14 = transformStats(solverStatsRaw["open14"]) open24 = transformStats(solverStatsRaw["open24"]) open34 = transformStats(solverStatsRaw["open34"]) open44 = transformStats(solverStatsRaw["open44"]) solverStats["open"] = zipStats( [open14, open24, open34, open44]) solverStats["open"].insert(0, [ 'Collected items', '1/4 locations available', '2/4 locations available', '3/4 locations available', '4/4 locations available' ]) # check that all items are present in the stats: nbItems = 19 nbLocs = 109 if itemsStats and len(itemsStats) != nbItems: for i, item in enumerate([ 'Bomb', 'Charge', 'Grapple', 'Gravity', 'HiJump', 'Ice', 'Missile', 'Morph', 'Plasma', 'PowerBomb', 'ScrewAttack', 'SpaceJump', 'Spazer', 'SpeedBooster', 'SpringBall', 'Super', 'Varia', 'Wave', 'XRayScope' ]): if itemsStats[i][1] != item: itemsStats.insert(i, [itemsStats[0][0], item] + [0] * nbLocs) else: itemsStats = None techniquesStats = None difficulties = None solverStats = None skillPresetContent = None majorsSplit = None (randoPresets, tourRandoPresets) = loadRandoPresetsList(self.cache, filter=True) (stdPresets, tourPresets, comPresets) = loadPresetsList(self.cache) return dict(stdPresets=stdPresets, tourPresets=tourPresets, randoPresets=randoPresets, tourRandoPresets=tourRandoPresets, itemsStats=itemsStats, techniquesStats=techniquesStats, categories=Knows.categories, knowsDesc=Knows.desc, skillPresetContent=skillPresetContent, locations=locations, majorsSplit=majorsSplit, difficulties=difficulties, solverStats=solverStats)