From 521d3b0584a19551d5f58cd7948745b6a2bbd4aa Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Tue, 30 Jun 2020 07:32:05 +0200 Subject: [PATCH] make larger trackers linked tables --- BaseClasses.py | 47 ++++++------ WebHost/__init__.py | 2 + WebHost/requirements.txt | 3 +- WebHost/static/jquery.scrollsync.js | 114 ++++++++++++++++++++++++++++ WebHost/templates/tracker.html | 38 ++++++++-- 5 files changed, 171 insertions(+), 33 deletions(-) create mode 100644 WebHost/static/jquery.scrollsync.js diff --git a/BaseClasses.py b/BaseClasses.py index 2176eb2a..8fcfe81c 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -436,26 +436,23 @@ class CollectionState(object): queue.extend(start.exits) # run BFS on all connections, and keep track of those blocked by missing items - while True: - try: - connection = queue.popleft() - new_region = connection.connected_region - if new_region in rrp: - bc.remove(connection) - elif connection.can_reach(self): - rrp.add(new_region) - bc.remove(connection) - bc.update(new_region.exits) - queue.extend(new_region.exits) - self.path[new_region] = (new_region.name, self.path.get(connection, None)) + while queue: + connection = queue.popleft() + new_region = connection.connected_region + if new_region in rrp: + bc.remove(connection) + elif connection.can_reach(self): + rrp.add(new_region) + bc.remove(connection) + bc.update(new_region.exits) + queue.extend(new_region.exits) + self.path[new_region] = (new_region.name, self.path.get(connection, None)) - # Retry connections if the new region can unblock them - if new_region.name in indirect_connections: - new_entrance = self.world.get_entrance(indirect_connections[new_region.name], player) - if new_entrance in bc and new_entrance not in queue: - queue.append(new_entrance) - except IndexError: - break + # Retry connections if the new region can unblock them + if new_region.name in indirect_connections: + new_entrance = self.world.get_entrance(indirect_connections[new_region.name], player) + if new_entrance in bc and new_entrance not in queue: + queue.append(new_entrance) def copy(self) -> CollectionState: ret = CollectionState(self.world) @@ -468,7 +465,7 @@ class CollectionState(object): ret.locations_checked = copy.copy(self.locations_checked) return ret - def can_reach(self, spot, resolution_hint=None, player=None): + def can_reach(self, spot, resolution_hint=None, player=None) -> bool: if not hasattr(spot, "spot_type"): # try to resolve a name if resolution_hint == 'Location': @@ -480,7 +477,7 @@ class CollectionState(object): spot = self.world.get_region(spot, player) return spot.can_reach(self) - def sweep_for_events(self, key_only=False, locations=None): + def sweep_for_events(self, key_only: bool = False, locations=None): # this may need improvement if locations is None: locations = self.world.get_filled_locations() @@ -488,7 +485,9 @@ class CollectionState(object): checked_locations = 0 while new_locations: reachable_events = [location for location in locations if location.event and - (not key_only or (not self.world.keyshuffle[location.item.player] and location.item.smallkey) or (not self.world.bigkeyshuffle[location.item.player] and location.item.bigkey)) + (not key_only or (not self.world.keyshuffle[ + location.item.player] and location.item.smallkey) or (not self.world.bigkeyshuffle[ + location.item.player] and location.item.bigkey)) and location.can_reach(self)] for event in reachable_events: if (event.name, event.player) not in self.events: @@ -497,12 +496,12 @@ class CollectionState(object): new_locations = len(reachable_events) > checked_locations checked_locations = len(reachable_events) - def has(self, item, player, count=1): + def has(self, item, player: int, count: int = 1): if count == 1: return (item, player) in self.prog_items return self.prog_items[item, player] >= count - def has_key(self, item, player, count=1): + def has_key(self, item, player, count: int = 1): if self.world.retro[player]: return self.can_buy_unlimited('Small Key (Universal)', player) if count == 1: diff --git a/WebHost/__init__.py b/WebHost/__init__.py index 156615c9..1a5a4957 100644 --- a/WebHost/__init__.py +++ b/WebHost/__init__.py @@ -11,6 +11,7 @@ from pony.flask import Pony from flask import Flask, request, redirect, url_for, render_template, Response, session, abort from flask_caching import Cache from flaskext.autoversion import Autoversion +from flask_compress import Compress from .models import * @@ -41,6 +42,7 @@ app.config["CACHE_TYPE"] = "simple" app.autoversion = True av = Autoversion(app) cache = Cache(app) +Compress(app) # this local cache is risky business if app hosting is done with subprocesses as it will not sync. Waitress is fine though multiworlds = {} diff --git a/WebHost/requirements.txt b/WebHost/requirements.txt index 5f284d5c..0b3d8f6f 100644 --- a/WebHost/requirements.txt +++ b/WebHost/requirements.txt @@ -2,4 +2,5 @@ flask>=1.1.2 pony>=0.7.13 waitress>=1.4.4 flask-caching>=1.9.0 -Flask-Autoversion>=0.1.0 \ No newline at end of file +Flask-Autoversion>=0.1.0 +Flask-Compress>=1.5.0 \ No newline at end of file diff --git a/WebHost/static/jquery.scrollsync.js b/WebHost/static/jquery.scrollsync.js new file mode 100644 index 00000000..9a0e7be9 --- /dev/null +++ b/WebHost/static/jquery.scrollsync.js @@ -0,0 +1,114 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery')) : + typeof define === 'function' && define.amd ? define(['exports', 'jquery'], factory) : + (factory((global.$ = global.$ || {}, global.$.fn = global.$.fn || {}), global.$)); +}(this, (function (exports, $) { + 'use strict'; + + $ = $ && $.hasOwnProperty('default') ? $['default'] : $; + +// 参考了(reference): +// debouncing function from John Hann +// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ + function debounce(func, threshold) { + var timeout; + return function debounced() { + var obj = this, args = arguments; + + function delayed() { + // 让调用smartresize的对象执行 + func.apply(obj, args); + /* + timeout = null;:这个语句只是单纯将timeout指向null, + 而timeout指向的定时器还存在, + 要想清除定时器(让setTimeout调用的函数不执行)要用clearTimeout(timeout)。 + eg: + var timeout = setTimeout(function(){ + alert('timeout = null');// 执行 + },1000); + timeout = null; + var timeout = setTimeout(function(){ + alert('clearTimeout(timeout)');// 不执行 + },1000); + clearTimeout(timeout); + var timeout = setTimeout(function(){ + clearTimeout(timeout); + alert('clearTimeout(timeout)');// 执行(已经开始执行匿名函数了) + },1000); + */ + timeout = null; + } + + // 如果有timeout正在倒计时,则清除当前timeout + timeout && clearTimeout(timeout); + timeout = setTimeout(delayed, threshold || 100); + }; + } + + function smartscroll(fn, threshold) { + return fn ? this.bind('scroll', debounce(fn, threshold)) : this.trigger('smartscroll'); + } + +//jquery-smartscroll + $.fn.smartscroll = smartscroll; + + function scrollsync(options) { + var defaluts = { + x_sync: true, + y_sync: true, + use_smartscroll: false, + smartscroll_delay: 10, + }; + + // 使用jQuery.extend 覆盖插件默认参数 + var options = $.extend({}, defaluts, options); + console.log(options); + + var scroll_type = options.use_smartscroll ? 'smartscroll' : 'scroll'; + var $containers = this; + + // 滚动后设置scrolling的值,调用set同步滚动条 + var scrolling = {}; + Object.defineProperty(scrolling, 'top', { + set: function (val) { + $containers.each(function () { + $(this).scrollTop(val); + }); + } + }); + Object.defineProperty(scrolling, 'left', { + set: function (val) { + $containers.each(function () { + $(this).scrollLeft(val); + }); + } + }); + + $containers.on({ + mouseover: function () { + if (scroll_type == 'smartscroll') { + $(this).smartscroll(function () { + options.x_sync && (scrolling.top = $(this).scrollTop()); + options.y_sync && (scrolling.left = $(this).scrollLeft()); + }, options.smartscroll_delay); + return; + } + $(this).bind('scroll', function () { + options.x_sync && (scrolling.top = $(this).scrollTop()); + options.y_sync && (scrolling.left = $(this).scrollLeft()); + }); + }, + mouseout: function () { + $(this).unbind('scroll'); + } + }); + + + return this; + } + + exports.scrollsync = scrollsync; + + Object.defineProperty(exports, '__esModule', {value: true}); + +}))); diff --git a/WebHost/templates/tracker.html b/WebHost/templates/tracker.html index ba673c7a..c85695b1 100644 --- a/WebHost/templates/tracker.html +++ b/WebHost/templates/tracker.html @@ -1,18 +1,24 @@ {% extends 'layout.html' %} {% block head %} Multiworld Tracker for Room {{ room.id }} + + + + - + {% endblock %} {% block body %} - {% for team, players in inventory.items() %} - - +
+ {% for team, players in inventory.items() %} +
+ @@ -86,8 +109,6 @@
# Name
{% endfor %} - - {% for team, players in checks_done.items() %} @@ -147,4 +168,5 @@
{% endfor %} + {% endblock %} \ No newline at end of file