Quellen-Filter über Trefferliste, dynamisches Filtering; Umlaut-Filter hinzugefügt/angepasst; Rahmen um Trefferliste
This commit is contained in:
142
app.py
142
app.py
@@ -7,86 +7,106 @@ app = Flask(__name__)
|
||||
|
||||
|
||||
def load_words() -> Tuple[List[str], Dict[str, List[str]]]:
|
||||
data_dir = Path(__file__).parent / "data"
|
||||
txt_path = data_dir / "words_de_5.txt"
|
||||
json_path = data_dir / "words_de_5_sources.json"
|
||||
data_dir = Path(__file__).parent / "data"
|
||||
txt_path = data_dir / "words_de_5.txt"
|
||||
json_path = data_dir / "words_de_5_sources.json"
|
||||
|
||||
words: List[str] = []
|
||||
sources_map: Dict[str, List[str]] = {}
|
||||
words: List[str] = []
|
||||
sources_map: Dict[str, List[str]] = {}
|
||||
|
||||
if txt_path.exists():
|
||||
with txt_path.open("r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
word = line.strip().lower()
|
||||
if len(word) == 5 and word.isalpha():
|
||||
words.append(word)
|
||||
if txt_path.exists():
|
||||
with txt_path.open("r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
word = line.strip().lower()
|
||||
if len(word) == 5 and word.isalpha():
|
||||
words.append(word)
|
||||
|
||||
if json_path.exists():
|
||||
try:
|
||||
sources_map = json.loads(json_path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
sources_map = {}
|
||||
if json_path.exists():
|
||||
try:
|
||||
sources_map = json.loads(json_path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
sources_map = {}
|
||||
|
||||
return words, sources_map
|
||||
return words, sources_map
|
||||
|
||||
|
||||
def filter_words(words: List[str], position_letters: List[str], includes_text: str, excludes_text: str) -> List[str]:
|
||||
results: List[str] = []
|
||||
includes_letters = [ch for ch in includes_text.lower() if ch.isalpha()]
|
||||
excludes_letters = [ch for ch in excludes_text.lower() if ch.isalpha()]
|
||||
for word in words:
|
||||
# feste Positionen
|
||||
if any(ch and word[idx] != ch for idx, ch in enumerate(position_letters)):
|
||||
continue
|
||||
# muss-enthalten
|
||||
if not all(ch in word for ch in includes_letters):
|
||||
continue
|
||||
# darf-nicht-enthalten
|
||||
if any(ch in word for ch in excludes_letters):
|
||||
continue
|
||||
results.append(word)
|
||||
return results
|
||||
results: List[str] = []
|
||||
includes_letters = [ch for ch in includes_text.lower() if ch.isalpha()]
|
||||
excludes_letters = [ch for ch in excludes_text.lower() if ch.isalpha()]
|
||||
for word in words:
|
||||
# feste Positionen
|
||||
if any(ch and word[idx] != ch for idx, ch in enumerate(position_letters)):
|
||||
continue
|
||||
# muss-enthalten
|
||||
if not all(ch in word for ch in includes_letters):
|
||||
continue
|
||||
# darf-nicht-enthalten
|
||||
if any(ch in word for ch in excludes_letters):
|
||||
continue
|
||||
results.append(word)
|
||||
return results
|
||||
|
||||
|
||||
@app.route("/", methods=["GET", "POST"])
|
||||
def index():
|
||||
all_words, sources_map = load_words()
|
||||
results: List[str] | None = None
|
||||
pos: List[str] = ["", "", "", "", ""]
|
||||
includes: str = ""
|
||||
excludes: str = ""
|
||||
if request.method == "POST":
|
||||
pos = [
|
||||
(request.form.get("pos1") or "").strip().lower(),
|
||||
(request.form.get("pos2") or "").strip().lower(),
|
||||
(request.form.get("pos3") or "").strip().lower(),
|
||||
(request.form.get("pos4") or "").strip().lower(),
|
||||
(request.form.get("pos5") or "").strip().lower(),
|
||||
]
|
||||
includes = (request.form.get("includes") or "").strip()
|
||||
excludes = (request.form.get("excludes") or "").strip()
|
||||
results = filter_words(all_words, pos, includes, excludes)
|
||||
return render_template(
|
||||
"index.html",
|
||||
results=results,
|
||||
pos=pos,
|
||||
includes=includes,
|
||||
excludes=excludes,
|
||||
words_count=len(all_words),
|
||||
sources_map=sources_map,
|
||||
)
|
||||
all_words, sources_map = load_words()
|
||||
results_display: List[str] | None = None
|
||||
pos: List[str] = ["", "", "", "", ""]
|
||||
includes: str = ""
|
||||
excludes: str = ""
|
||||
use_ot: bool = True
|
||||
use_wf: bool = False
|
||||
if request.method == "POST":
|
||||
pos = [
|
||||
(request.form.get("pos1") or "").strip().lower(),
|
||||
(request.form.get("pos2") or "").strip().lower(),
|
||||
(request.form.get("pos3") or "").strip().lower(),
|
||||
(request.form.get("pos4") or "").strip().lower(),
|
||||
(request.form.get("pos5") or "").strip().lower(),
|
||||
]
|
||||
includes = (request.form.get("includes") or "").strip()
|
||||
excludes = (request.form.get("excludes") or "").strip()
|
||||
use_ot = request.form.get("use_ot") is not None
|
||||
use_wf = request.form.get("use_wf") is not None
|
||||
|
||||
# 1) Buchstaben-/Positionssuche über alle Wörter
|
||||
matched = filter_words(all_words, pos, includes, excludes)
|
||||
# 2) Quellen-Filter nur auf Ergebnisansicht anwenden
|
||||
allowed = set()
|
||||
if use_ot:
|
||||
allowed.add("ot")
|
||||
if use_wf:
|
||||
allowed.add("wf")
|
||||
if allowed:
|
||||
results_display = [w for w in matched if any(src in allowed for src in sources_map.get(w, []))]
|
||||
else:
|
||||
# Keine Quelle gewählt → leere Anzeige (Suche wurde dennoch ausgeführt)
|
||||
results_display = []
|
||||
return render_template(
|
||||
"index.html",
|
||||
results=results_display,
|
||||
pos=pos,
|
||||
includes=includes,
|
||||
excludes=excludes,
|
||||
words_count=len(all_words),
|
||||
sources_map=sources_map,
|
||||
use_ot=use_ot,
|
||||
use_wf=use_wf,
|
||||
error_message=None,
|
||||
)
|
||||
|
||||
|
||||
@app.route('/manifest.webmanifest')
|
||||
def manifest_file():
|
||||
return send_from_directory(Path(__file__).parent / 'static', 'manifest.webmanifest', mimetype='application/manifest+json')
|
||||
return send_from_directory(Path(__file__).parent / 'static', 'manifest.webmanifest', mimetype='application/manifest+json')
|
||||
|
||||
|
||||
@app.route('/sw.js')
|
||||
def service_worker():
|
||||
# Service Worker muss auf Top-Level liegen
|
||||
return send_from_directory(Path(__file__).parent / 'static', 'sw.js', mimetype='application/javascript')
|
||||
# Service Worker muss auf Top-Level liegen
|
||||
return send_from_directory(Path(__file__).parent / 'static', 'sw.js', mimetype='application/javascript')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
||||
app.run(debug=True)
|
||||
|
Reference in New Issue
Block a user