summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2025-05-26 15:55:29 +0200
committererdgeist <erdgeist@erdgeist.org>2025-05-26 15:55:29 +0200
commit47cb23ce1f991c21ceb9273cf4bed717a09abd9a (patch)
tree90f6e3299abf5ec632123513fc80959f3336e15e
Kickoff commit
-rw-r--r--Makefile6
-rw-r--r--augment.py194
-rw-r--r--csp.js181
-rw-r--r--data.json86
-rw-r--r--example-output.txt912
-rw-r--r--index.html13
-rw-r--r--requirements.txt1
-rw-r--r--style.css21
-rw-r--r--tabularasa.js284
9 files changed, 1698 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6d50316
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,6 @@
1install: venv
2 venv/bin/pip install --upgrade pip
3 venv/bin/pip install -r requirements.txt
4
5venv:
6 python3 -m venv ./venv
diff --git a/augment.py b/augment.py
new file mode 100644
index 0000000..d96d511
--- /dev/null
+++ b/augment.py
@@ -0,0 +1,194 @@
1import json
2from pprint import pprint
3from random import randrange, randint
4
5league_count = 4
6tabelle = []
7
8with open('data.json') as f:
9 data = json.load(f)
10
11ident = 0
12for o in data["orte"]:
13 o["id"] = ident
14 o["raucher"] = not randrange(2)
15 o["teams"] = []
16 ident += 1
17
18ident = 0
19for t in data["teams"]:
20
21 t["id"] = ident
22 t["tag"] = randrange(7)
23 t["liga"] = randrange(league_count)
24 t["nichtraucher"] = not randrange(4)
25
26 team_nr = t["nichtraucher"]
27
28 found = False
29 while not found:
30 heimort = randrange(len(data["orte"]))
31 ersatzort = randrange(len(data["orte"]))
32
33 if data["orte"][ersatzort]["raucher"]:
34 continue
35
36 ort_nr = not data["orte"][heimort]["raucher"]
37
38 if team_nr != ort_nr:
39 continue
40
41 if team_nr:
42 ersatzort = -1
43
44 found = True
45
46 t["ersatzort"] = ersatzort
47 t["heimort"] = heimort
48 data["orte"][heimort]["teams"].append(ident)
49
50 ident += 1
51
52# Count necessary spieltage
53max_spieltage = 0
54for league in range(league_count):
55 pairings_count = len([t for t in data["teams"] if t["liga"] == league])
56 if pairings_count % 2:
57 pairings_count += 1
58 max_spieltage = max(2 * (pairings_count - 1), max_spieltage);
59
60print( "Max Spieltage: ", max_spieltage)
61
62# Fill Tabelle with our demo data
63ident = 0
64for league in range(league_count):
65 league_teams = [t for t in data["teams"] if t["liga"] == league]
66
67 for team_a in league_teams:
68 game_count = 0
69
70 for team_b in league_teams:
71 if team_a["id"] == team_b["id"]: continue
72
73 # If Heimspiel-Team is smokers and the Gastteam is not, the alternative
74 # location needs to be chosen
75 ort = next((ort for ort in data["orte"] if ort["id"] == team_a["heimort"]), None)
76 if team_b["nichtraucher"] and ort["raucher"]:
77 ort = next((ort for ort in data["orte"] if ort["id"] == team_a["ersatzort"]), None)
78
79 tabelle.append({"team_a": team_a["id"], "team_b": team_b["id"], "liga": league, "ort": ort["id"], "tag": team_a["tag"], "id": ident})
80 ident += 1
81 game_count += 1
82
83 while game_count < max_spieltage / 2:
84 tabelle.append({"team_a": team_a["id"], "team_b": -1, "liga": league, "ort": -1, "tag": -1, "id": ident})
85 ident += 1
86 tabelle.append({"team_a": -1, "team_b": team_a["id"], "liga": league, "ort": -1, "tag": -1, "id": ident})
87 ident += 1
88 game_count += 1
89
90rueckrundenstart = max_spieltage // 2
91
92from ortools.sat.python import cp_model
93model = cp_model.CpModel()
94
95variables = {game["id"]: model.new_int_var(0, max_spieltage - 1, f"game{game['id']}") for game in tabelle}
96
97# Make sure each team only plays once each spieltag
98for team in data["teams"]:
99 # team_games = [game["id"] for game in tabelle if game["team_a"] == team["id"] or game["team_b"] == team["id"]]
100 # print (len(team_games), team_games, team)
101 model.add_all_different([variables[game["id"]] for game in tabelle if game["team_a"] == team["id"] or game["team_b"] == team["id"]])
102
103# Make sure each ort is only used once per spieltag+week
104for ort in data["orte"]:
105 ort_games = [game for game in tabelle if game["ort"] == ort["id"]]
106 for tag in list({game["tag"] for game in ort_games}):
107 model.add_all_different([variables[game["id"]] for game in ort_games if game["tag"] == tag ])
108
109# Make sure that Rueckrundenspiele only happen at Rueckrunde
110for game in tabelle:
111 # Don't force this constraint on wildcard games
112 if game["ort"] == -1: continue
113
114 # Find Rueckspiel
115 rueckspiel = next((candidate for candidate in tabelle if candidate["team_a"] == game["team_b"] and candidate["team_b"] == game["team_a"]), None)
116
117 va = variables[game["id"]]
118 vb = variables[rueckspiel["id"]]
119
120 runde_a = model.new_int_var(0, 1, "tmpa")
121 runde_b = model.new_int_var(0, 1, "tmpb")
122
123 model.add_division_equality(runde_a, va, rueckrundenstart)
124 model.add_division_equality(runde_b, vb, rueckrundenstart)
125 model.add(runde_a != runde_b)
126
127# Make sure that Heimspiele and Gastspiele alternate
128violations = []
129for team in data["teams"]:
130 heimspiele = [candidate for candidate in tabelle if candidate["team_a"] == team["id"] ]
131
132 for heimspiel in heimspiele:
133 for conflict in heimspiele:
134 if heimspiel["id"] == conflict["id"]: continue
135
136 va = variables[heimspiel["id"]]
137 vb = variables[conflict["id"]]
138
139 tmpdiff_a = model.new_int_var(-max_spieltage, max_spieltage, "tmpa")
140 tmpdiff_b = model.new_int_var(-max_spieltage, max_spieltage, "tmpb")
141
142 model.add(tmpdiff_a == va - vb)
143 model.add(tmpdiff_b == vb - va)
144
145 tmpconsequtive_a = model.new_bool_var("tmpa")
146 tmpconsequtive_b = model.new_bool_var("tmpb")
147
148 model.add(tmpdiff_a == 1).only_enforce_if(tmpconsequtive_a)
149 model.add(tmpdiff_a != 1).only_enforce_if(tmpconsequtive_a.Not())
150
151 model.add(tmpdiff_b == 1).only_enforce_if(tmpconsequtive_b)
152 model.add(tmpdiff_b != 1).only_enforce_if(tmpconsequtive_b.Not())
153
154 is_consecutive = model.new_bool_var('is_consecutive')
155
156 model.add_bool_or([tmpconsequtive_a, tmpconsequtive_b]).OnlyEnforceIf(is_consecutive)
157 model.add_bool_and([tmpconsequtive_a.Not(), tmpconsequtive_b.Not()]).OnlyEnforceIf(is_consecutive.Not())
158
159 violations.append(is_consecutive)
160
161model.minimize(sum(violations))
162
163print ("All set, solving")
164
165solver = cp_model.CpSolver()
166solver.parameters.max_time_in_seconds = 30.0
167solver.parameters.random_seed = randint(0, 1_000_000)
168status = solver.solve(model)
169print(status, solver.status_name())
170
171from sys import exit
172if status == cp_model.INFEASIBLE:
173 exit(-1)
174
175for game in tabelle:
176 game["spieltag"] = solver.value(variables[game["id"]])
177
178# tabelle.sort(key=lambda game: game["spieltag"])
179
180# PRINT OUT RESULTS AS TABLE
181all_teams = {team["id"]: team for team in data["teams"]}
182all_teams[-1] = {"name": "*"}
183all_orte = {ort["id"]: ort for ort in data["orte"]}
184all_orte[-1] = {"name": "*"}
185
186for league in range(league_count):
187 league_tabelle = [game for game in tabelle if game["liga"] == league]
188 league_tabelle.sort(key=lambda game: game["spieltag"])
189
190 for game in league_tabelle:
191 print(game["spieltag"], all_teams[game["team_a"]]["name"], "::", all_teams[game["team_b"]]["name"], "::", all_orte[game["ort"]]["name"])
192
193#print( json.dumps(data))
194#print( json.dumps(tabelle))
diff --git a/csp.js b/csp.js
new file mode 100644
index 0000000..139b70d
--- /dev/null
+++ b/csp.js
@@ -0,0 +1,181 @@
1!function() {
2
3var CSP = {},
4 FAILURE = 'FAILURE',
5 stepCounter = 0;
6
7CSP.solve = function solve(csp) {
8 // Solves a constraint satisfaction problem.
9 // `csp` is an object that should have the properties:
10 // `variables` : object that holds variable names and their domain.
11 // `constraints`: list of constraints where each element is an
12 // array of [head node, tail node, constraint function]
13 // `cb`: callback function for visualizing assignments. It is passed in
14 // an "assigned" object, an "unassigned" object, and `csp`.
15 // `timeStep`: milliseconds between invocations of `cb`.
16
17 csp.timeStep = csp.timeStep || 1;
18 var result = backtrack({}, csp.variables, csp);
19 if (result == FAILURE) { return result; }
20 // Unwrap values from array containers.
21 for (var key in result) {
22 result[key] = result[key][0];
23 }
24 return result;
25}
26
27function backtrack(_assigned, unassigned, csp) {
28 // Backtracking search.
29
30 // Copying assigned in necessary because we modify it. Without copying
31 // the object over, modifying assigned would also change values for old
32 // assigned objects (which are used in callbacks).
33 var assigned = {};
34 for (var key in _assigned) { assigned[key] = _assigned[key]; }
35
36 if (finished(unassigned)) { return assigned; } // Base case.
37 var nextKey = selectUnassignedVariable(unassigned),
38 values = orderValues(nextKey, assigned, unassigned, csp);
39 delete unassigned[nextKey];
40
41 for (var i = 0; i < values.length; i++) {
42 stepCounter++;
43 assigned[nextKey] = [values[i]]; // Assign a value to a variable.
44 var consistent = enforceConsistency(assigned, unassigned, csp);
45 var newUnassigned = {}, newAssigned = {};
46 for (var key in consistent) {
47 if (assigned[key]) { newAssigned[key] = assigned[key].slice(); }
48 else { newUnassigned[key] = consistent[key].slice(); }
49 }
50 if (csp.cb) {
51 setTimeout(
52 // Need a closure to fix values of newAssigned and newUnassigned.
53 // Otherwise, _every_ call of the callback takes the on values of the last iteration.
54 (function (newAssigned, newUnassigned) {
55 return function () { csp.cb(newAssigned, newUnassigned, csp); };
56 })(newAssigned, newUnassigned),
57 stepCounter * csp.timeStep
58 );
59 }
60 if (anyEmpty(consistent)) { continue; } // Empty domains means failure.
61 var result = backtrack(newAssigned, newUnassigned, csp);
62 if (result != FAILURE) { return result; }
63 }
64
65 return FAILURE;
66}
67
68function finished(unassigned) {
69 // Checks if there are no more variables to assign.
70 return Object.keys(unassigned).length == 0;
71}
72
73function anyEmpty(consistent) {
74 // Checks if any variable's domain is empty.
75 for (var key in consistent) {
76 if (consistent[key].length == 0) { return true; }
77 }
78 return false;
79}
80
81function partialAssignment(assigned, unassigned) {
82 // Combine unassigned and assigned for use in enforceConsistency.
83 var partial = {};
84 for (var key in unassigned) { partial[key] = unassigned[key].slice(); }
85 for (var key in assigned) { partial[key] = assigned[key].slice(); }
86 return partial;
87}
88
89function enforceConsistency(assigned, unassigned, csp) {
90 // Enforces arc consistency by removing inconsistent values from
91 // every constraint's tail node.
92
93 function removeInconsistentValues(head, tail, constraint, variables) {
94 // Removes inconsistent values from the tail node. A value is
95 // inconsistent when if the `tail` is assigned that value, there are
96 // no values in `head`'s domain that satisfies the constraint.
97 var hv = variables[head], tv = variables[tail];
98 var validTailValues = tv.filter(function (t) {
99 return hv.some(function (h) {
100 return constraint(h, t);
101 });
102 });
103 var removed = tv.length != validTailValues.length;
104 variables[tail] = validTailValues;
105 return removed;
106 }
107
108 function incomingConstraints(node) {
109 // Returns all the constraints where `node` is the head node.
110 return csp.constraints.filter(function (c) {
111 return c[0] == node;
112 });
113 }
114
115 var queue = csp.constraints.slice(),
116 variables = partialAssignment(assigned, unassigned);
117 while (queue.length) { // While there are more constraints to test.
118 var c = queue.shift(), head = c[0], tail = c[1], constraint = c[2];
119 if (removeInconsistentValues(head, tail, constraint, variables)) {
120 // If values from the tail have been removed, incoming constraints
121 // to the tail must be rechecked.
122 queue = queue.concat(incomingConstraints(tail));
123 }
124 }
125 return variables;
126}
127
128function selectUnassignedVariable(unassigned) {
129 // Picks the next variable to assign according to the Minimum
130 // Remaining Values heuristic. Pick the variable with the fewest
131 // values remaining in its domain. This helps identify domain
132 // failures earlier.
133 var minKey = null, minLen = Number.POSITIVE_INFINITY;
134 for (var key in unassigned) {
135 var len = unassigned[key].length;
136 if (len < minLen) { minKey = key, minLen = len; }
137 }
138 return minKey;
139}
140
141function orderValues(nextKey, assigned, unassigned, csp) {
142 // Orders the values of an unassigned variable according to the
143 // Least Constraining Values heuristic. Perform arc consistency
144 // on each possible value, and order variables according to the
145 // how many values were eliminated from all the domains (fewest
146 // eliminated in the front). This helps makes success more likely
147 // by keeping future options open.
148
149 function countValues(vars) {
150 var sum = 0;
151 for (var key in vars) { sum += vars[key].length; }
152 return sum;
153 }
154
155 function valuesEliminated(val) {
156 assigned[nextKey] = [val];
157 var newLength = countValues(enforceConsistency(assigned, unassigned, csp));
158 delete assigned[nextKey];
159 return newLength;
160 }
161
162 // Cache valuesEliminated to be used in sort.
163 var cache = {}, values = unassigned[nextKey];
164 values.forEach(function(val) {
165 cache[val] = valuesEliminated(val);
166 });
167 // Descending order based on the number of domain values remaining.
168 values.sort(function (a, b) { return cache[b] - cache[a]; });
169 return values;
170}
171
172// Taken from d3 source. Makes `csp` usable in other scripts.
173if (typeof define === 'function' && define.amd) {
174 define(CSP);
175} else if (typeof module === 'object' && module.exports) {
176 module.exports = CSP;
177} else {
178 this.csp = CSP;
179}
180
181}();
diff --git a/data.json b/data.json
new file mode 100644
index 0000000..8e6c1fa
--- /dev/null
+++ b/data.json
@@ -0,0 +1,86 @@
1{
2 "teams": [
3 {"name": "Die Stangendreher" },
4 {"name": "FC Kurbelkraft" },
5 {"name": "Die Kugelblitze" },
6 {"name": "Drehmoment 04" },
7 {"name": "Kickerknacker" },
8 {"name": "Stangenterror" },
9 {"name": "Die Plattenpanther" },
10 {"name": "Vollstoff United" },
11 {"name": "Kurbelkönige" },
12 {"name": "Die Gleitlager" },
13 {"name": "Dynamo Drehpunkt" },
14 {"name": "FC Hartkurbel" },
15 {"name": "Turbo-Tischkicker" },
16 {"name": "Kugelkontrolle" },
17 {"name": "Die Griffbanditen" },
18 {"name": "Tischgewitter" },
19 {"name": "Rapid Rotation" },
20 {"name": "Kurbelschmiede" },
21 {"name": "Die Schussscheiben" },
22 {"name": "Die Querpassquäler" },
23 {"name": "Reibungslose Racker" },
24 {"name": "Die Kugeljäger" },
25 {"name": "Kurbelclub Chaos" },
26 {"name": "Die Seitenwechsel" },
27 {"name": "Drehakademie" },
28 {"name": "Die Griffgötter" },
29 {"name": "Kickerkombinat" },
30 {"name": "Rotationssportverein" },
31 {"name": "Die Rillenritter" },
32 {"name": "Stangenhelden" },
33 {"name": "Kugelkommando" },
34 {"name": "Kick’n’Twist" },
35 {"name": "FC Schubkraft" },
36 {"name": "Die Rutschbahn-Raketen" },
37 {"name": "Die Taktikdreher" },
38 {"name": "Die Kickkanonen" },
39 {"name": "Die Blockbuster" },
40 {"name": "Vollgas Vierer" },
41 {"name": "Die Tischwölfe" },
42 {"name": "Rotation Rangers" },
43 {"name": "Die Drehlords" },
44 {"name": "Griffbereit 99" },
45 {"name": "Die Bandenkrieger" },
46 {"name": "Ballmagneten" },
47 {"name": "Stahlstangen SC" },
48 {"name": "Die Kurbelkicker" },
49 {"name": "Die Abroller" },
50 {"name": "Die Plattenspieler" },
51 {"name": "FC Gummipuffer" },
52 {"name": "Griff & Gloria" }
53 ],
54 "orte": [
55 {"name": "Kurbelpark Arena" },
56 {"name": "Stangenstadion Nord" },
57 {"name": "Drehpunkt Dome" },
58 {"name": "Griffhalle West" },
59 {"name": "Kugelwerk Ost" },
60 {"name": "Twistground Central" },
61 {"name": "Reibungsring Arena" },
62 {"name": "Plattenpalast" },
63 {"name": "Kickerforum SĂĽd" },
64 {"name": "Drehkraft-Dome" },
65 {"name": "Tischkampfarena Alte Platte" },
66 {"name": "Kurbelkurve Stadion" },
67 {"name": "Stangenwelle Stadion" },
68 {"name": "Magnetfeld Mitte" },
69 {"name": "Arena am Gleittisch" },
70 {"name": "Schusshof Kurbeldorf" },
71 {"name": "Rotationshalle 7" },
72 {"name": "Griffzentrum Westkurve" },
73 {"name": "Bandenbruch-Stadion" },
74 {"name": "Kugeltempel Altstadt" },
75 {"name": "Twistpark Westrand" },
76 {"name": "GegenstoĂź-Galerie" },
77 {"name": "Kurbelaue Nord" },
78 {"name": "Kickerklotz Kolosseum" },
79 {"name": "Griffgipfel Arena" },
80 {"name": "Der Tischkessel" },
81 {"name": "Lagerblock SĂĽd" },
82 {"name": "Kugelkurve Klassik" },
83 {"name": "Die Platte am Fluss" },
84 {"name": "Haltepunkt Hohlgriff" }
85 ]
86}
diff --git a/example-output.txt b/example-output.txt
new file mode 100644
index 0000000..05d35d2
--- /dev/null
+++ b/example-output.txt
@@ -0,0 +1,912 @@
10 FC Kurbelkraft :: Rotation Rangers :: Stangenwelle Stadion
20 Kickerknacker :: Die Kickkanonen :: Stangenwelle Stadion
30 Kugelkontrolle :: Rapid Rotation :: Die Platte am Fluss
40 Die Seitenwechsel :: FC Schubkraft :: Kurbelpark Arena
50 * :: Kugelkommando :: *
60 * :: Die Taktikdreher :: *
71 * :: FC Kurbelkraft :: *
81 * :: Kugelkontrolle :: *
91 Rapid Rotation :: Kickerknacker :: Kugeltempel Altstadt
101 * :: Die Seitenwechsel :: *
111 Kugelkommando :: Rotation Rangers :: Twistpark Westrand
121 FC Schubkraft :: * :: *
131 Die Taktikdreher :: Die Kickkanonen :: Kurbelaue Nord
142 FC Kurbelkraft :: Rapid Rotation :: Stangenstadion Nord
152 Kickerknacker :: Kugelkommando :: Stangenwelle Stadion
162 Kugelkontrolle :: FC Schubkraft :: Die Platte am Fluss
172 Die Seitenwechsel :: Die Kickkanonen :: Schusshof Kurbeldorf
182 * :: Die Taktikdreher :: *
192 Rotation Rangers :: * :: *
203 * :: FC Kurbelkraft :: *
213 * :: Kickerknacker :: *
223 * :: Kugelkontrolle :: *
233 Rapid Rotation :: Die Seitenwechsel :: Kugeltempel Altstadt
243 Kugelkommando :: Die Kickkanonen :: Twistpark Westrand
253 FC Schubkraft :: Rotation Rangers :: Griffzentrum Westkurve
263 Die Taktikdreher :: * :: *
274 FC Kurbelkraft :: FC Schubkraft :: Stangenstadion Nord
284 Kickerknacker :: Die Taktikdreher :: Haltepunkt Hohlgriff
294 Die Seitenwechsel :: Kugelkontrolle :: Kurbelpark Arena
304 Kugelkommando :: Rapid Rotation :: Twistpark Westrand
314 Die Kickkanonen :: * :: *
324 Rotation Rangers :: * :: *
335 * :: FC Kurbelkraft :: *
345 * :: Kickerknacker :: *
355 Kugelkontrolle :: * :: *
365 Rapid Rotation :: * :: *
375 Die Seitenwechsel :: * :: *
385 * :: Kugelkommando :: *
395 FC Schubkraft :: * :: *
405 Die Taktikdreher :: * :: *
415 * :: Die Kickkanonen :: *
425 * :: Rotation Rangers :: *
436 FC Kurbelkraft :: * :: *
446 Kickerknacker :: * :: *
456 * :: Rapid Rotation :: *
466 * :: Die Seitenwechsel :: *
476 Kugelkommando :: Die Taktikdreher :: Twistpark Westrand
486 * :: FC Schubkraft :: *
496 Die Kickkanonen :: Kugelkontrolle :: Griffgipfel Arena
506 Rotation Rangers :: * :: *
517 * :: FC Kurbelkraft :: *
527 Kugelkontrolle :: Kugelkommando :: Kickerklotz Kolosseum
537 Rapid Rotation :: Die Taktikdreher :: Kugeltempel Altstadt
547 Die Seitenwechsel :: Rotation Rangers :: Schusshof Kurbeldorf
557 FC Schubkraft :: Kickerknacker :: Rotationshalle 7
567 * :: Die Kickkanonen :: *
578 Kickerknacker :: FC Kurbelkraft :: Haltepunkt Hohlgriff
588 Kugelkommando :: Die Seitenwechsel :: Twistpark Westrand
598 * :: FC Schubkraft :: *
608 Die Taktikdreher :: Kugelkontrolle :: Die Platte am Fluss
618 Die Kickkanonen :: * :: *
628 Rotation Rangers :: Rapid Rotation :: Kickerforum SĂĽd
639 FC Kurbelkraft :: Die Taktikdreher :: Stangenstadion Nord
649 Kugelkontrolle :: Kickerknacker :: Die Platte am Fluss
659 Rapid Rotation :: Die Kickkanonen :: Twistpark Westrand
669 Die Seitenwechsel :: * :: *
679 * :: Kugelkommando :: *
689 FC Schubkraft :: * :: *
699 * :: Rotation Rangers :: *
7010 FC Kurbelkraft :: Die Seitenwechsel :: Stangenstadion Nord
7110 Kickerknacker :: * :: *
7210 * :: Rapid Rotation :: *
7310 Kugelkommando :: * :: *
7410 Die Taktikdreher :: FC Schubkraft :: Die Platte am Fluss
7510 Die Kickkanonen :: * :: *
7610 Rotation Rangers :: Kugelkontrolle :: Kickerforum SĂĽd
7711 * :: Kickerknacker :: *
7811 Kugelkontrolle :: FC Kurbelkraft :: Die Platte am Fluss
7911 * :: Rapid Rotation :: *
8011 Die Seitenwechsel :: * :: *
8111 FC Schubkraft :: Kugelkommando :: Griffzentrum Westkurve
8211 * :: Die Kickkanonen :: *
8311 Rotation Rangers :: Die Taktikdreher :: Kickerforum SĂĽd
8412 Kickerknacker :: Die Seitenwechsel :: Haltepunkt Hohlgriff
8512 * :: Kugelkontrolle :: *
8612 Rapid Rotation :: * :: *
8712 Kugelkommando :: * :: *
8812 * :: FC Schubkraft :: *
8912 * :: Die Taktikdreher :: *
9012 Die Kickkanonen :: FC Kurbelkraft :: Griffgipfel Arena
9112 * :: Rotation Rangers :: *
9213 FC Kurbelkraft :: * :: *
9313 * :: Kickerknacker :: *
9413 Kugelkontrolle :: * :: *
9513 * :: Kugelkommando :: *
9613 FC Schubkraft :: Rapid Rotation :: Rotationshalle 7
9713 Die Taktikdreher :: Die Seitenwechsel :: Die Platte am Fluss
9813 Rotation Rangers :: Die Kickkanonen :: Kickerforum SĂĽd
9914 Kickerknacker :: Rotation Rangers :: Stangenwelle Stadion
10014 * :: Kugelkontrolle :: *
10114 * :: Rapid Rotation :: *
10214 Die Seitenwechsel :: * :: *
10314 Kugelkommando :: FC Kurbelkraft :: Twistpark Westrand
10414 * :: Die Taktikdreher :: *
10514 Die Kickkanonen :: FC Schubkraft :: Griffgipfel Arena
10615 Kugelkontrolle :: * :: *
10715 Rapid Rotation :: FC Kurbelkraft :: Kugeltempel Altstadt
10815 FC Schubkraft :: Die Seitenwechsel :: Rotationshalle 7
10915 Die Taktikdreher :: Kickerknacker :: Die Platte am Fluss
11015 * :: Die Kickkanonen :: *
11115 Rotation Rangers :: Kugelkommando :: Kickerforum SĂĽd
11216 FC Kurbelkraft :: * :: *
11316 * :: Kugelkontrolle :: *
11416 Die Seitenwechsel :: Rapid Rotation :: Kurbelpark Arena
11516 Kugelkommando :: Kickerknacker :: Twistpark Westrand
11616 FC Schubkraft :: * :: *
11716 Die Kickkanonen :: Die Taktikdreher :: Griffgipfel Arena
11816 * :: Rotation Rangers :: *
11917 Kickerknacker :: * :: *
12017 Kugelkontrolle :: * :: *
12117 Rapid Rotation :: * :: *
12217 * :: FC Schubkraft :: *
12317 Die Taktikdreher :: FC Kurbelkraft :: Die Platte am Fluss
12417 Die Kickkanonen :: Kugelkommando :: Griffgipfel Arena
12517 Rotation Rangers :: Die Seitenwechsel :: Kickerforum SĂĽd
12618 FC Kurbelkraft :: Kugelkontrolle :: Stangenstadion Nord
12718 Rapid Rotation :: * :: *
12818 Die Seitenwechsel :: * :: *
12918 Kugelkommando :: * :: *
13018 FC Schubkraft :: * :: *
13118 * :: Die Taktikdreher :: *
13218 * :: Die Kickkanonen :: *
13318 Rotation Rangers :: Kickerknacker :: Kickerforum SĂĽd
13419 * :: FC Kurbelkraft :: *
13519 Kickerknacker :: Rapid Rotation :: Haltepunkt Hohlgriff
13619 Kugelkontrolle :: Rotation Rangers :: Kickerklotz Kolosseum
13719 * :: FC Schubkraft :: *
13819 Die Taktikdreher :: Kugelkommando :: Kurbelaue Nord
13919 Die Kickkanonen :: Die Seitenwechsel :: Griffgipfel Arena
14020 FC Kurbelkraft :: Kickerknacker :: Stangenstadion Nord
14120 Rapid Rotation :: * :: *
14220 Die Seitenwechsel :: Die Taktikdreher :: Kurbelpark Arena
14320 Kugelkommando :: Kugelkontrolle :: Twistpark Westrand
14420 FC Schubkraft :: * :: *
14520 Die Kickkanonen :: * :: *
14620 Rotation Rangers :: * :: *
14721 FC Kurbelkraft :: * :: *
14821 Kickerknacker :: * :: *
14921 Kugelkontrolle :: Die Kickkanonen :: Kickerklotz Kolosseum
15021 Rapid Rotation :: * :: *
15121 * :: Die Seitenwechsel :: *
15221 Kugelkommando :: FC Schubkraft :: Twistpark Westrand
15321 Die Taktikdreher :: Rotation Rangers :: Kurbelaue Nord
15422 * :: FC Kurbelkraft :: *
15522 * :: Rapid Rotation :: *
15622 Die Seitenwechsel :: Kugelkommando :: Schusshof Kurbeldorf
15722 FC Schubkraft :: Kugelkontrolle :: Rotationshalle 7
15822 Die Taktikdreher :: * :: *
15922 Die Kickkanonen :: Kickerknacker :: Griffgipfel Arena
16022 Rotation Rangers :: * :: *
16123 FC Kurbelkraft :: * :: *
16223 Kickerknacker :: FC Schubkraft :: Haltepunkt Hohlgriff
16323 Rapid Rotation :: Kugelkontrolle :: Kugeltempel Altstadt
16423 * :: Die Seitenwechsel :: *
16523 Kugelkommando :: * :: *
16623 * :: Die Taktikdreher :: *
16723 Die Kickkanonen :: * :: *
16823 * :: Rotation Rangers :: *
16924 * :: Kickerknacker :: *
17024 Kugelkontrolle :: * :: *
17124 Die Seitenwechsel :: * :: *
17224 * :: Kugelkommando :: *
17324 FC Schubkraft :: FC Kurbelkraft :: Rotationshalle 7
17424 Die Taktikdreher :: Rapid Rotation :: Die Platte am Fluss
17524 * :: Die Kickkanonen :: *
17624 Rotation Rangers :: * :: *
17725 FC Kurbelkraft :: Kugelkommando :: Stangenwelle Stadion
17825 Kickerknacker :: Kugelkontrolle :: Haltepunkt Hohlgriff
17925 Rapid Rotation :: FC Schubkraft :: Kugeltempel Altstadt
18025 * :: Die Seitenwechsel :: *
18125 Die Taktikdreher :: * :: *
18225 Die Kickkanonen :: Rotation Rangers :: Griffgipfel Arena
18326 * :: Kickerknacker :: *
18426 Kugelkontrolle :: * :: *
18526 Die Seitenwechsel :: FC Kurbelkraft :: Kurbelpark Arena
18626 Kugelkommando :: * :: *
18726 Die Taktikdreher :: * :: *
18826 Die Kickkanonen :: Rapid Rotation :: Griffgipfel Arena
18926 Rotation Rangers :: FC Schubkraft :: Kickerforum SĂĽd
19027 FC Kurbelkraft :: Die Kickkanonen :: Stangenwelle Stadion
19127 Kickerknacker :: * :: *
19227 * :: Kugelkontrolle :: *
19327 Rapid Rotation :: Kugelkommando :: Twistpark Westrand
19427 * :: Die Seitenwechsel :: *
19527 FC Schubkraft :: Die Taktikdreher :: Rotationshalle 7
19627 * :: Rotation Rangers :: *
19728 Kugelkontrolle :: Die Taktikdreher :: Die Platte am Fluss
19828 * :: Rapid Rotation :: *
19928 Die Seitenwechsel :: Kickerknacker :: Kurbelpark Arena
20028 Kugelkommando :: * :: *
20128 * :: FC Schubkraft :: *
20228 Die Kickkanonen :: * :: *
20328 Rotation Rangers :: FC Kurbelkraft :: Kickerforum SĂĽd
20429 FC Kurbelkraft :: * :: *
20529 Kickerknacker :: * :: *
20629 Kugelkontrolle :: Die Seitenwechsel :: Die Platte am Fluss
20729 Rapid Rotation :: Rotation Rangers :: Twistpark Westrand
20829 * :: Kugelkommando :: *
20929 FC Schubkraft :: Die Kickkanonen :: Griffzentrum Westkurve
21029 Die Taktikdreher :: * :: *
2110 Die Kugelblitze :: Drehmoment 04 :: Haltepunkt Hohlgriff
2120 Die Querpassquäler :: Kurbelkönige :: Der Tischkessel
2130 Kick’n’Twist :: * :: *
2140 Die Rutschbahn-Raketen :: Die Gleitlager :: Kurbelaue Nord
2150 Griffbereit 99 :: * :: *
2160 Ballmagneten :: Turbo-Tischkicker :: Twistpark Westrand
2170 Stahlstangen SC :: Die Stangendreher :: Griffgipfel Arena
2181 Drehmoment 04 :: Die Stangendreher :: Plattenpalast
2191 Kurbelkönige :: Die Kugelblitze :: Griffgipfel Arena
2201 Die Gleitlager :: Griffbereit 99 :: Kickerklotz Kolosseum
2211 Turbo-Tischkicker :: * :: *
2221 * :: Die Querpassquäler :: *
2231 * :: Kick’n’Twist :: *
2241 * :: Die Rutschbahn-Raketen :: *
2251 Ballmagneten :: Stahlstangen SC :: Twistpark Westrand
2262 * :: Die Kugelblitze :: *
2272 Drehmoment 04 :: Die Gleitlager :: Rotationshalle 7
2282 * :: Kurbelkönige :: *
2292 * :: Turbo-Tischkicker :: *
2302 Die Rutschbahn-Raketen :: Die Querpassquäler :: Kurbelaue Nord
2312 Griffbereit 99 :: Die Stangendreher :: Kickerforum SĂĽd
2322 * :: Ballmagneten :: *
2332 Stahlstangen SC :: Kick’n’Twist :: Griffgipfel Arena
2343 Die Stangendreher :: * :: *
2353 Die Kugelblitze :: Die Gleitlager :: Haltepunkt Hohlgriff
2363 Drehmoment 04 :: Die Querpassquäler :: Rotationshalle 7
2373 Turbo-Tischkicker :: Stahlstangen SC :: Plattenpalast
2383 Kick’n’Twist :: Kurbelkönige :: Griffgipfel Arena
2393 Griffbereit 99 :: Die Rutschbahn-Raketen :: Kickerforum SĂĽd
2403 Ballmagneten :: * :: *
2414 Die Kugelblitze :: * :: *
2424 Drehmoment 04 :: Kick’n’Twist :: Rotationshalle 7
2434 Kurbelkönige :: Griffbereit 99 :: Griffgipfel Arena
2444 Die Gleitlager :: Die Stangendreher :: Kickerklotz Kolosseum
2454 Turbo-Tischkicker :: Die Querpassquäler :: Kurbelkurve Stadion
2464 Die Rutschbahn-Raketen :: Ballmagneten :: Kurbelaue Nord
2474 Stahlstangen SC :: * :: *
2485 * :: Die Kugelblitze :: *
2495 * :: Kurbelkönige :: *
2505 Die Gleitlager :: * :: *
2515 Turbo-Tischkicker :: Die Rutschbahn-Raketen :: Plattenpalast
2525 Die Querpassquäler :: Stahlstangen SC :: Der Tischkessel
2535 Kick’n’Twist :: * :: *
2545 Griffbereit 99 :: Drehmoment 04 :: Kickerforum SĂĽd
2555 Ballmagneten :: Die Stangendreher :: Twistpark Westrand
2566 Die Stangendreher :: * :: *
2576 Die Kugelblitze :: Ballmagneten :: Bandenbruch-Stadion
2586 Drehmoment 04 :: * :: *
2596 Kurbelkönige :: * :: *
2606 * :: Die Gleitlager :: *
2616 Kick’n’Twist :: Die Querpassquäler :: Griffhalle West
2626 Die Rutschbahn-Raketen :: Stahlstangen SC :: Kurbelaue Nord
2636 Griffbereit 99 :: Turbo-Tischkicker :: Kickerforum SĂĽd
2647 Die Stangendreher :: Turbo-Tischkicker :: Griffgipfel Arena
2657 * :: Drehmoment 04 :: *
2667 Die Gleitlager :: * :: *
2677 Die Querpassquäler :: * :: *
2687 Kick’n’Twist :: Griffbereit 99 :: Griffgipfel Arena
2697 Die Rutschbahn-Raketen :: Kurbelkönige :: Kurbelaue Nord
2707 Ballmagneten :: * :: *
2717 Stahlstangen SC :: Die Kugelblitze :: Griffgipfel Arena
2728 Die Kugelblitze :: Die Stangendreher :: Bandenbruch-Stadion
2738 Kurbelkönige :: Drehmoment 04 :: Griffgipfel Arena
2748 Turbo-Tischkicker :: Die Gleitlager :: Kurbelkurve Stadion
2758 * :: Die Rutschbahn-Raketen :: *
2768 Griffbereit 99 :: Die Querpassquäler :: Kickerforum Süd
2778 Ballmagneten :: Kick’n’Twist :: Twistpark Westrand
2788 * :: Stahlstangen SC :: *
2799 Die Stangendreher :: Kick’n’Twist :: Griffgipfel Arena
2809 Die Kugelblitze :: Turbo-Tischkicker :: Haltepunkt Hohlgriff
2819 * :: Kurbelkönige :: *
2829 Die Gleitlager :: * :: *
2839 Die Querpassquäler :: Ballmagneten :: Der Tischkessel
2849 Die Rutschbahn-Raketen :: * :: *
2859 * :: Griffbereit 99 :: *
2869 Stahlstangen SC :: Drehmoment 04 :: Griffgipfel Arena
28710 * :: Die Stangendreher :: *
28810 * :: Die Kugelblitze :: *
28910 Kurbelkönige :: Ballmagneten :: Griffgipfel Arena
29010 Turbo-Tischkicker :: * :: *
29110 * :: Die Querpassquäler :: *
29210 Kick’n’Twist :: Die Gleitlager :: Griffhalle West
29310 Die Rutschbahn-Raketen :: Drehmoment 04 :: Kurbelaue Nord
29410 Griffbereit 99 :: * :: *
29510 * :: Stahlstangen SC :: *
29611 Die Stangendreher :: * :: *
29711 Die Kugelblitze :: Die Rutschbahn-Raketen :: Bandenbruch-Stadion
29811 * :: Drehmoment 04 :: *
29911 Die Gleitlager :: Ballmagneten :: Kickerklotz Kolosseum
30011 Die Querpassquäler :: * :: *
30111 Kick’n’Twist :: Turbo-Tischkicker :: Griffhalle West
30211 * :: Griffbereit 99 :: *
30311 Stahlstangen SC :: Kurbelkönige :: Griffgipfel Arena
30412 Drehmoment 04 :: Turbo-Tischkicker :: Rotationshalle 7
30512 Kurbelkönige :: Die Stangendreher :: Griffgipfel Arena
30612 Die Querpassquäler :: Die Gleitlager :: Drehpunkt Dome
30712 Die Rutschbahn-Raketen :: Kick’n’Twist :: Kurbelaue Nord
30812 Griffbereit 99 :: Die Kugelblitze :: Kickerforum SĂĽd
30912 * :: Ballmagneten :: *
31012 * :: Stahlstangen SC :: *
31113 Die Stangendreher :: Die Rutschbahn-Raketen :: Griffgipfel Arena
31213 Die Kugelblitze :: Die Querpassquäler :: Haltepunkt Hohlgriff
31313 * :: Drehmoment 04 :: *
31413 Turbo-Tischkicker :: Kurbelkönige :: Plattenpalast
31513 Kick’n’Twist :: * :: *
31613 Ballmagneten :: Griffbereit 99 :: Twistpark Westrand
31713 Stahlstangen SC :: Die Gleitlager :: Griffgipfel Arena
31814 Drehmoment 04 :: Ballmagneten :: Plattenpalast
31914 Die Gleitlager :: Kurbelkönige :: Kickerklotz Kolosseum
32014 * :: Turbo-Tischkicker :: *
32114 Die Querpassquäler :: Die Stangendreher :: Der Tischkessel
32214 Kick’n’Twist :: Die Kugelblitze :: Griffhalle West
32314 * :: Die Rutschbahn-Raketen :: *
32414 Griffbereit 99 :: Stahlstangen SC :: Kickerforum SĂĽd
32515 Die Stangendreher :: Die Gleitlager :: Griffgipfel Arena
32615 Kurbelkönige :: * :: *
32715 Turbo-Tischkicker :: * :: *
32815 * :: Kick’n’Twist :: *
32915 Die Rutschbahn-Raketen :: Die Kugelblitze :: Kurbelaue Nord
33015 * :: Griffbereit 99 :: *
33115 Ballmagneten :: Drehmoment 04 :: Twistpark Westrand
33215 Stahlstangen SC :: Die Querpassquäler :: Griffgipfel Arena
33316 * :: Die Stangendreher :: *
33416 Die Kugelblitze :: Stahlstangen SC :: Bandenbruch-Stadion
33516 * :: Kurbelkönige :: *
33616 Die Gleitlager :: Die Rutschbahn-Raketen :: Kickerklotz Kolosseum
33716 * :: Turbo-Tischkicker :: *
33816 Die Querpassquäler :: Drehmoment 04 :: Drehpunkt Dome
33916 Kick’n’Twist :: Ballmagneten :: Griffgipfel Arena
34016 Griffbereit 99 :: * :: *
34117 Die Stangendreher :: Die Kugelblitze :: Griffgipfel Arena
34217 Kurbelkönige :: Die Querpassquäler :: Griffgipfel Arena
34317 * :: Die Gleitlager :: *
34417 Turbo-Tischkicker :: Drehmoment 04 :: Kurbelkurve Stadion
34517 * :: Kick’n’Twist :: *
34617 Die Rutschbahn-Raketen :: Griffbereit 99 :: Kurbelaue Nord
34717 Ballmagneten :: * :: *
34817 Stahlstangen SC :: * :: *
34918 Die Stangendreher :: Ballmagneten :: Griffgipfel Arena
35018 Die Kugelblitze :: * :: *
35118 Drehmoment 04 :: Kurbelkönige :: Plattenpalast
35218 Die Gleitlager :: * :: *
35318 Die Querpassquäler :: Turbo-Tischkicker :: Drehpunkt Dome
35418 Griffbereit 99 :: Kick’n’Twist :: Kickerforum Süd
35518 Stahlstangen SC :: Die Rutschbahn-Raketen :: Griffgipfel Arena
35619 Drehmoment 04 :: Griffbereit 99 :: Plattenpalast
35719 Kurbelkönige :: Die Gleitlager :: Griffgipfel Arena
35819 Turbo-Tischkicker :: Die Kugelblitze :: Kurbelkurve Stadion
35919 Kick’n’Twist :: * :: *
36019 Die Rutschbahn-Raketen :: Die Stangendreher :: Kurbelaue Nord
36119 Ballmagneten :: Die Querpassquäler :: Twistpark Westrand
36219 * :: Stahlstangen SC :: *
36320 Die Stangendreher :: Griffbereit 99 :: Griffgipfel Arena
36420 Die Kugelblitze :: * :: *
36520 Kurbelkönige :: Stahlstangen SC :: Griffgipfel Arena
36620 Die Gleitlager :: Drehmoment 04 :: Stangenstadion Nord
36720 Turbo-Tischkicker :: Ballmagneten :: Plattenpalast
36820 Die Querpassquäler :: Die Rutschbahn-Raketen :: Der Tischkessel
36920 * :: Kick’n’Twist :: *
37021 Die Kugelblitze :: Kurbelkönige :: Bandenbruch-Stadion
37121 Drehmoment 04 :: * :: *
37221 * :: Turbo-Tischkicker :: *
37321 Die Querpassquäler :: * :: *
37421 Kick’n’Twist :: Die Stangendreher :: Griffgipfel Arena
37521 Die Rutschbahn-Raketen :: * :: *
37621 Ballmagneten :: Die Gleitlager :: Twistpark Westrand
37721 Stahlstangen SC :: Griffbereit 99 :: Griffgipfel Arena
37822 Die Stangendreher :: Stahlstangen SC :: Griffgipfel Arena
37922 * :: Die Kugelblitze :: *
38022 * :: Drehmoment 04 :: *
38122 Kurbelkönige :: * :: *
38222 * :: Die Gleitlager :: *
38322 Turbo-Tischkicker :: Griffbereit 99 :: Plattenpalast
38422 * :: Die Querpassquäler :: *
38522 Kick’n’Twist :: Die Rutschbahn-Raketen :: Griffgipfel Arena
38622 * :: Ballmagneten :: *
38723 * :: Die Stangendreher :: *
38823 Drehmoment 04 :: Die Rutschbahn-Raketen :: Plattenpalast
38923 Die Gleitlager :: Kick’n’Twist :: Stangenstadion Nord
39023 Die Querpassquäler :: Die Kugelblitze :: Drehpunkt Dome
39123 * :: Griffbereit 99 :: *
39223 Ballmagneten :: Kurbelkönige :: Twistpark Westrand
39323 Stahlstangen SC :: Turbo-Tischkicker :: Griffgipfel Arena
39424 Die Stangendreher :: * :: *
39524 Die Kugelblitze :: Kick’n’Twist :: Haltepunkt Hohlgriff
39624 Drehmoment 04 :: * :: *
39724 Kurbelkönige :: Die Rutschbahn-Raketen :: Griffgipfel Arena
39824 Die Gleitlager :: Die Querpassquäler :: Stangenstadion Nord
39924 Turbo-Tischkicker :: * :: *
40024 Griffbereit 99 :: Ballmagneten :: Kickerforum SĂĽd
40124 Stahlstangen SC :: * :: *
40225 * :: Die Stangendreher :: *
40325 Die Kugelblitze :: Griffbereit 99 :: Bandenbruch-Stadion
40425 Drehmoment 04 :: * :: *
40525 Kurbelkönige :: Turbo-Tischkicker :: Griffgipfel Arena
40625 Die Gleitlager :: Stahlstangen SC :: Kickerklotz Kolosseum
40725 Die Querpassquäler :: Kick’n’Twist :: Drehpunkt Dome
40825 Die Rutschbahn-Raketen :: * :: *
40925 Ballmagneten :: * :: *
41026 Die Stangendreher :: Drehmoment 04 :: Griffgipfel Arena
41126 Kurbelkönige :: Kick’n’Twist :: Griffgipfel Arena
41226 Die Gleitlager :: Die Kugelblitze :: Stangenstadion Nord
41326 Die Querpassquäler :: * :: *
41426 Die Rutschbahn-Raketen :: Turbo-Tischkicker :: Kurbelaue Nord
41526 Griffbereit 99 :: * :: *
41626 Stahlstangen SC :: Ballmagneten :: Griffgipfel Arena
41727 Die Stangendreher :: Die Querpassquäler :: Griffgipfel Arena
41827 Drehmoment 04 :: Stahlstangen SC :: Plattenpalast
41927 * :: Die Gleitlager :: *
42027 Turbo-Tischkicker :: Kick’n’Twist :: Kurbelkurve Stadion
42127 * :: Die Rutschbahn-Raketen :: *
42227 Griffbereit 99 :: Kurbelkönige :: Kickerforum Süd
42327 Ballmagneten :: Die Kugelblitze :: Twistpark Westrand
42428 Die Kugelblitze :: * :: *
42528 Kurbelkönige :: * :: *
42628 Turbo-Tischkicker :: Die Stangendreher :: Plattenpalast
42728 * :: Die Querpassquäler :: *
42828 Kick’n’Twist :: Drehmoment 04 :: Griffhalle West
42928 Die Rutschbahn-Raketen :: * :: *
43028 Griffbereit 99 :: Die Gleitlager :: Kickerforum SĂĽd
43128 * :: Ballmagneten :: *
43228 Stahlstangen SC :: * :: *
43329 Die Stangendreher :: Kurbelkönige :: Griffgipfel Arena
43429 Drehmoment 04 :: Die Kugelblitze :: Rotationshalle 7
43529 Die Gleitlager :: Turbo-Tischkicker :: Stangenstadion Nord
43629 Die Querpassquäler :: Griffbereit 99 :: Der Tischkessel
43729 Kick’n’Twist :: Stahlstangen SC :: Griffgipfel Arena
43829 Ballmagneten :: Die Rutschbahn-Raketen :: Twistpark Westrand
4390 Die Plattenpanther :: Kurbelschmiede :: Die Platte am Fluss
4400 Vollstoff United :: * :: *
4410 Dynamo Drehpunkt :: * :: *
4420 Reibungslose Racker :: Kickerkombinat :: Der Tischkessel
4430 Drehakademie :: Die Abroller :: Kugeltempel Altstadt
4440 Die Griffgötter :: Die Plattenspieler :: Kugelwerk Ost
4450 Die Blockbuster :: Die Kurbelkicker :: Kugeltempel Altstadt
4460 Die Drehlords :: * :: *
4471 * :: Die Plattenpanther :: *
4481 Vollstoff United :: Kickerkombinat :: Kugelkurve Klassik
4491 * :: Reibungslose Racker :: *
4501 Drehakademie :: Kurbelschmiede :: Kugeltempel Altstadt
4511 Die Griffgötter :: Die Abroller :: Kugelwerk Ost
4521 Die Blockbuster :: * :: *
4531 Die Drehlords :: Die Kurbelkicker :: Griffhalle West
4541 Die Plattenspieler :: Dynamo Drehpunkt :: Kurbelkurve Stadion
4552 Die Plattenpanther :: Die Drehlords :: Die Platte am Fluss
4562 Vollstoff United :: Die Kurbelkicker :: Kugelkurve Klassik
4572 Dynamo Drehpunkt :: Kurbelschmiede :: Kugelkurve Klassik
4582 Reibungslose Racker :: Die Blockbuster :: Der Tischkessel
4592 Drehakademie :: * :: *
4602 Die Griffgötter :: Kickerkombinat :: Kugelwerk Ost
4612 Die Abroller :: Die Plattenspieler :: Rotationshalle 7
4623 Vollstoff United :: Dynamo Drehpunkt :: Kugelkurve Klassik
4633 Kurbelschmiede :: * :: *
4643 * :: Reibungslose Racker :: *
4653 Drehakademie :: Die Plattenpanther :: Kugeltempel Altstadt
4663 Die Griffgötter :: * :: *
4673 Kickerkombinat :: Die Drehlords :: Drehpunkt Dome
4683 Die Blockbuster :: * :: *
4693 Die Kurbelkicker :: Die Plattenspieler :: Drehkraft-Dome
4703 * :: Die Abroller :: *
4714 Die Plattenpanther :: * :: *
4724 Vollstoff United :: Die Griffgötter :: Kugelkurve Klassik
4734 Dynamo Drehpunkt :: * :: *
4744 Kurbelschmiede :: Die Abroller :: GegenstoĂź-Galerie
4754 Reibungslose Racker :: * :: *
4764 Kickerkombinat :: Die Blockbuster :: Drehpunkt Dome
4774 Die Drehlords :: Drehakademie :: Griffhalle West
4784 * :: Die Kurbelkicker :: *
4794 Die Plattenspieler :: * :: *
4805 * :: Vollstoff United :: *
4815 Kurbelschmiede :: Kickerkombinat :: GegenstoĂź-Galerie
4825 Drehakademie :: Die Plattenspieler :: Kugeltempel Altstadt
4835 * :: Die Griffgötter :: *
4845 Die Blockbuster :: Die Plattenpanther :: Kugeltempel Altstadt
4855 Die Drehlords :: Dynamo Drehpunkt :: Griffhalle West
4865 Die Kurbelkicker :: * :: *
4875 Die Abroller :: Reibungslose Racker :: Twistpark Westrand
4886 Vollstoff United :: Die Blockbuster :: Kugelkurve Klassik
4896 Kurbelschmiede :: Die Kurbelkicker :: GegenstoĂź-Galerie
4906 Reibungslose Racker :: Dynamo Drehpunkt :: Der Tischkessel
4916 Die Griffgötter :: Drehakademie :: Kugelwerk Ost
4926 Kickerkombinat :: Die Plattenpanther :: Drehpunkt Dome
4936 Die Drehlords :: Die Plattenspieler :: Griffhalle West
4946 * :: Die Abroller :: *
4957 Die Plattenpanther :: Reibungslose Racker :: Stangenwelle Stadion
4967 Dynamo Drehpunkt :: Die Blockbuster :: Kugelkurve Klassik
4977 Drehakademie :: Vollstoff United :: Kugeltempel Altstadt
4987 Kickerkombinat :: Die Plattenspieler :: Drehpunkt Dome
4997 Die Drehlords :: Kurbelschmiede :: Griffhalle West
5007 Die Kurbelkicker :: Die Griffgötter :: Drehkraft-Dome
5017 Die Abroller :: * :: *
5028 Vollstoff United :: * :: *
5038 Dynamo Drehpunkt :: Die Plattenpanther :: Kugelkurve Klassik
5048 Kurbelschmiede :: * :: *
5058 * :: Drehakademie :: *
5068 Die Griffgötter :: Reibungslose Racker :: Schusshof Kurbeldorf
5078 Die Blockbuster :: Die Plattenspieler :: Kugeltempel Altstadt
5088 Die Drehlords :: Die Abroller :: Griffhalle West
5098 Die Kurbelkicker :: Kickerkombinat :: Drehkraft-Dome
5109 Die Plattenpanther :: Die Plattenspieler :: Die Platte am Fluss
5119 Reibungslose Racker :: Kurbelschmiede :: Der Tischkessel
5129 Drehakademie :: * :: *
5139 Die Griffgötter :: * :: *
5149 Kickerkombinat :: Dynamo Drehpunkt :: Drehpunkt Dome
5159 Die Drehlords :: Die Blockbuster :: Griffhalle West
5169 * :: Die Kurbelkicker :: *
5179 Die Abroller :: Vollstoff United :: Rotationshalle 7
51810 * :: Die Plattenpanther :: *
51910 Kurbelschmiede :: * :: *
52010 * :: Kickerkombinat :: *
52110 Die Blockbuster :: Drehakademie :: Kugeltempel Altstadt
52210 Die Drehlords :: Die Griffgötter :: Griffhalle West
52310 Die Kurbelkicker :: Reibungslose Racker :: Lagerblock SĂĽd
52410 Die Abroller :: Dynamo Drehpunkt :: Rotationshalle 7
52510 Die Plattenspieler :: Vollstoff United :: Kurbelkurve Stadion
52611 Vollstoff United :: Reibungslose Racker :: Plattenpalast
52711 Drehakademie :: Dynamo Drehpunkt :: Kugeltempel Altstadt
52811 Die Griffgötter :: Die Plattenpanther :: Kugelwerk Ost
52911 Kickerkombinat :: * :: *
53011 Die Blockbuster :: * :: *
53111 * :: Die Drehlords :: *
53211 Die Abroller :: Die Kurbelkicker :: Rotationshalle 7
53311 Die Plattenspieler :: Kurbelschmiede :: Kurbelkurve Stadion
53412 Dynamo Drehpunkt :: * :: *
53512 Reibungslose Racker :: Die Plattenspieler :: Der Tischkessel
53612 Die Griffgötter :: Kurbelschmiede :: Kugelwerk Ost
53712 Kickerkombinat :: Drehakademie :: Drehpunkt Dome
53812 Die Drehlords :: Vollstoff United :: Griffhalle West
53912 Die Kurbelkicker :: Die Plattenpanther :: Drehkraft-Dome
54012 Die Abroller :: Die Blockbuster :: Rotationshalle 7
54113 Die Plattenpanther :: Die Abroller :: Die Platte am Fluss
54213 Kurbelschmiede :: Vollstoff United :: GegenstoĂź-Galerie
54313 Drehakademie :: Reibungslose Racker :: Stangenwelle Stadion
54413 * :: Kickerkombinat :: *
54513 Die Blockbuster :: Die Griffgötter :: Kugeltempel Altstadt
54613 * :: Die Drehlords :: *
54713 Die Kurbelkicker :: Dynamo Drehpunkt :: Drehkraft-Dome
54813 Die Plattenspieler :: * :: *
54914 Vollstoff United :: Die Plattenpanther :: Kugelkurve Klassik
55014 Die Griffgötter :: Dynamo Drehpunkt :: Kugelwerk Ost
55114 Die Blockbuster :: Kurbelschmiede :: Kugeltempel Altstadt
55214 Die Drehlords :: Reibungslose Racker :: Kurbelaue Nord
55314 Die Kurbelkicker :: Drehakademie :: Drehkraft-Dome
55414 Die Abroller :: Kickerkombinat :: Rotationshalle 7
55514 * :: Die Plattenspieler :: *
55615 Die Plattenpanther :: Vollstoff United :: Die Platte am Fluss
55715 * :: Dynamo Drehpunkt :: *
55815 Reibungslose Racker :: * :: *
55915 * :: Die Griffgötter :: *
56015 * :: Die Blockbuster :: *
56115 Die Drehlords :: Kickerkombinat :: Griffhalle West
56215 * :: Die Kurbelkicker :: *
56315 Die Abroller :: Kurbelschmiede :: Rotationshalle 7
56415 Die Plattenspieler :: Drehakademie :: Kurbelkurve Stadion
56516 * :: Vollstoff United :: *
56616 Dynamo Drehpunkt :: Die Plattenspieler :: Kugelkurve Klassik
56716 * :: Kurbelschmiede :: *
56816 Reibungslose Racker :: Die Plattenpanther :: Der Tischkessel
56916 * :: Drehakademie :: *
57016 Die Griffgötter :: * :: *
57116 Die Blockbuster :: Kickerkombinat :: Kugeltempel Altstadt
57216 Die Kurbelkicker :: Die Drehlords :: Drehkraft-Dome
57316 * :: Die Abroller :: *
57417 Kurbelschmiede :: Dynamo Drehpunkt :: GegenstoĂź-Galerie
57517 * :: Reibungslose Racker :: *
57617 Drehakademie :: Die Drehlords :: Kugeltempel Altstadt
57717 Kickerkombinat :: Die Griffgötter :: Drehpunkt Dome
57817 Die Kurbelkicker :: Vollstoff United :: Drehkraft-Dome
57917 Die Abroller :: Die Plattenpanther :: Rotationshalle 7
58017 Die Plattenspieler :: Die Blockbuster :: Kurbelkurve Stadion
58118 Die Plattenpanther :: * :: *
58218 * :: Dynamo Drehpunkt :: *
58318 Reibungslose Racker :: * :: *
58418 * :: Drehakademie :: *
58518 Die Blockbuster :: Vollstoff United :: Kugeltempel Altstadt
58618 * :: Die Drehlords :: *
58718 Die Kurbelkicker :: Kurbelschmiede :: Drehkraft-Dome
58818 Die Abroller :: Die Griffgötter :: Rotationshalle 7
58918 Die Plattenspieler :: Kickerkombinat :: Kurbelkurve Stadion
59019 Dynamo Drehpunkt :: Vollstoff United :: Kugelkurve Klassik
59119 Kurbelschmiede :: Die Plattenpanther :: GegenstoĂź-Galerie
59219 Drehakademie :: * :: *
59319 * :: Die Griffgötter :: *
59419 Kickerkombinat :: Reibungslose Racker :: Kickerforum SĂĽd
59519 * :: Die Blockbuster :: *
59619 Die Kurbelkicker :: Die Abroller :: Drehkraft-Dome
59719 Die Plattenspieler :: Die Drehlords :: Kurbelkurve Stadion
59820 Vollstoff United :: * :: *
59920 * :: Dynamo Drehpunkt :: *
60020 Kurbelschmiede :: Die Plattenspieler :: GegenstoĂź-Galerie
60120 Die Griffgötter :: Die Kurbelkicker :: Kugelwerk Ost
60220 Kickerkombinat :: * :: *
60320 Die Blockbuster :: Reibungslose Racker :: Twistpark Westrand
60420 Die Drehlords :: Die Plattenpanther :: Griffhalle West
60520 Die Abroller :: Drehakademie :: Rotationshalle 7
60621 Die Plattenpanther :: * :: *
60721 Drehakademie :: Die Kurbelkicker :: Kugeltempel Altstadt
60821 Die Griffgötter :: Vollstoff United :: Kugelwerk Ost
60921 Kickerkombinat :: Kurbelschmiede :: Drehpunkt Dome
61021 Die Blockbuster :: Dynamo Drehpunkt :: Kugeltempel Altstadt
61121 Die Abroller :: Die Drehlords :: Rotationshalle 7
61221 Die Plattenspieler :: Reibungslose Racker :: Griffzentrum Westkurve
61322 Dynamo Drehpunkt :: Die Kurbelkicker :: Kugelkurve Klassik
61422 Kurbelschmiede :: Die Griffgötter :: Gegenstoß-Galerie
61522 Reibungslose Racker :: Die Abroller :: Der Tischkessel
61622 Drehakademie :: Die Blockbuster :: Kugeltempel Altstadt
61722 Kickerkombinat :: Vollstoff United :: Drehpunkt Dome
61822 Die Drehlords :: * :: *
61922 Die Plattenspieler :: Die Plattenpanther :: Kurbelkurve Stadion
62023 Die Plattenpanther :: Die Kurbelkicker :: Die Platte am Fluss
62123 Dynamo Drehpunkt :: Die Abroller :: Kugelkurve Klassik
62223 Kurbelschmiede :: Die Drehlords :: GegenstoĂź-Galerie
62323 Reibungslose Racker :: Vollstoff United :: Der Tischkessel
62423 Drehakademie :: Kickerkombinat :: Kugeltempel Altstadt
62523 * :: Die Blockbuster :: *
62623 Die Plattenspieler :: Die Griffgötter :: Kurbelkurve Stadion
62724 Die Plattenpanther :: Die Blockbuster :: Die Platte am Fluss
62824 Vollstoff United :: Drehakademie :: Kugelkurve Klassik
62924 Dynamo Drehpunkt :: Kickerkombinat :: Kugelkurve Klassik
63024 * :: Kurbelschmiede :: *
63124 Reibungslose Racker :: Die Kurbelkicker :: Der Tischkessel
63224 Die Griffgötter :: Die Drehlords :: Kugelwerk Ost
63324 Die Abroller :: * :: *
63424 * :: Die Plattenspieler :: *
63525 Die Plattenpanther :: Kickerkombinat :: Die Platte am Fluss
63625 Vollstoff United :: Die Plattenspieler :: Kugelkurve Klassik
63725 Dynamo Drehpunkt :: Die Drehlords :: Kugelkurve Klassik
63825 Kurbelschmiede :: Drehakademie :: GegenstoĂź-Galerie
63925 Reibungslose Racker :: Die Griffgötter :: Der Tischkessel
64025 Die Blockbuster :: Die Abroller :: Kugeltempel Altstadt
64125 Die Kurbelkicker :: * :: *
64226 Die Plattenpanther :: Die Griffgötter :: Die Platte am Fluss
64326 * :: Vollstoff United :: *
64426 Dynamo Drehpunkt :: Drehakademie :: Kugelkurve Klassik
64526 Kurbelschmiede :: Die Blockbuster :: GegenstoĂź-Galerie
64626 Reibungslose Racker :: Die Drehlords :: Der Tischkessel
64726 Kickerkombinat :: * :: *
64826 Die Abroller :: * :: *
64926 Die Plattenspieler :: Die Kurbelkicker :: Kurbelkurve Stadion
65027 Die Plattenpanther :: Drehakademie :: Die Platte am Fluss
65127 Vollstoff United :: Die Abroller :: Kugelkurve Klassik
65227 Dynamo Drehpunkt :: Die Griffgötter :: Kugelkurve Klassik
65327 Kurbelschmiede :: Reibungslose Racker :: Griffzentrum Westkurve
65427 * :: Kickerkombinat :: *
65527 Die Blockbuster :: Die Drehlords :: Kugeltempel Altstadt
65627 Die Kurbelkicker :: * :: *
65727 Die Plattenspieler :: * :: *
65828 * :: Die Plattenpanther :: *
65928 Vollstoff United :: Die Drehlords :: Kugelkurve Klassik
66028 Dynamo Drehpunkt :: Reibungslose Racker :: Twistpark Westrand
66128 * :: Kurbelschmiede :: *
66228 Drehakademie :: Die Griffgötter :: Kugeltempel Altstadt
66328 Kickerkombinat :: Die Abroller :: Drehpunkt Dome
66428 Die Kurbelkicker :: Die Blockbuster :: Drehkraft-Dome
66528 * :: Die Plattenspieler :: *
66629 Die Plattenpanther :: Dynamo Drehpunkt :: Die Platte am Fluss
66729 Vollstoff United :: Kurbelschmiede :: Kugelkurve Klassik
66829 Reibungslose Racker :: Drehakademie :: Der Tischkessel
66929 Die Griffgötter :: Die Blockbuster :: Kugelwerk Ost
67029 Kickerkombinat :: Die Kurbelkicker :: Drehpunkt Dome
67129 Die Drehlords :: * :: *
67229 Die Plattenspieler :: Die Abroller :: Kurbelkurve Stadion
6730 Stangenterror :: Die Bandenkrieger :: Kugelwerk Ost
6740 FC Hartkurbel :: Griff & Gloria :: Drehkraft-Dome
6750 Die Griffbanditen :: Tischgewitter :: Schusshof Kurbeldorf
6760 Die Schussscheiben :: Die Kugeljäger :: Kickerklotz Kolosseum
6770 * :: Kurbelclub Chaos :: *
6780 Stangenhelden :: Die Rillenritter :: Bandenbruch-Stadion
6790 Vollgas Vierer :: Die Tischwölfe :: Gegenstoß-Galerie
6800 FC Gummipuffer :: Rotationssportverein :: Arena am Gleittisch
6811 Die Griffbanditen :: Die Schussscheiben :: Schusshof Kurbeldorf
6821 Tischgewitter :: Stangenterror :: Griffgipfel Arena
6831 Kurbelclub Chaos :: Stangenhelden :: Tischkampfarena Alte Platte
6841 Rotationssportverein :: FC Hartkurbel :: Drehkraft-Dome
6851 Die Rillenritter :: FC Gummipuffer :: Kickerklotz Kolosseum
6861 Vollgas Vierer :: Griff & Gloria :: GegenstoĂź-Galerie
6871 Die Tischwölfe :: * :: *
6881 Die Bandenkrieger :: Die Kugeljäger :: Griffzentrum Westkurve
6892 Stangenterror :: Die Schussscheiben :: Twistground Central
6902 Die Kugeljäger :: Kurbelclub Chaos :: Griffgipfel Arena
6912 Rotationssportverein :: * :: *
6922 Die Rillenritter :: Die Griffbanditen :: Kickerklotz Kolosseum
6932 Vollgas Vierer :: Stangenhelden :: GegenstoĂź-Galerie
6942 Die Tischwölfe :: FC Hartkurbel :: Gegenstoß-Galerie
6952 Die Bandenkrieger :: Tischgewitter :: Griffzentrum Westkurve
6962 Griff & Gloria :: FC Gummipuffer :: Drehkraft-Dome
6973 FC Hartkurbel :: * :: *
6983 Die Griffbanditen :: Vollgas Vierer :: Haltepunkt Hohlgriff
6993 Tischgewitter :: FC Gummipuffer :: Griffgipfel Arena
7003 Kurbelclub Chaos :: Stangenterror :: Tischkampfarena Alte Platte
7013 Die Rillenritter :: Die Kugeljäger :: Kickerklotz Kolosseum
7023 Die Tischwölfe :: Stangenhelden :: Gegenstoß-Galerie
7033 Die Bandenkrieger :: Rotationssportverein :: Drehkraft-Dome
7043 Griff & Gloria :: Die Schussscheiben :: Schusshof Kurbeldorf
7054 Stangenterror :: Rotationssportverein :: Kugelwerk Ost
7064 Tischgewitter :: Vollgas Vierer :: Griffgipfel Arena
7074 * :: Die Schussscheiben :: *
7084 Die Kugeljäger :: Die Tischwölfe :: Griffgipfel Arena
7094 Die Rillenritter :: FC Hartkurbel :: Kickerklotz Kolosseum
7104 Stangenhelden :: Die Bandenkrieger :: Die Platte am Fluss
7114 FC Gummipuffer :: Kurbelclub Chaos :: Schusshof Kurbeldorf
7124 Griff & Gloria :: Die Griffbanditen :: Drehkraft-Dome
7135 Stangenterror :: Vollgas Vierer :: Kugelwerk Ost
7145 FC Hartkurbel :: Die Bandenkrieger :: Drehkraft-Dome
7155 Die Griffbanditen :: FC Gummipuffer :: Haltepunkt Hohlgriff
7165 Tischgewitter :: Rotationssportverein :: Griffgipfel Arena
7175 Die Schussscheiben :: Die Rillenritter :: Kickerklotz Kolosseum
7185 Die Kugeljäger :: Stangenhelden :: Griffgipfel Arena
7195 Kurbelclub Chaos :: Die Tischwölfe :: Tischkampfarena Alte Platte
7205 * :: Griff & Gloria :: *
7216 Die Schussscheiben :: Rotationssportverein :: Kickerklotz Kolosseum
7226 Die Kugeljäger :: FC Hartkurbel :: Griffgipfel Arena
7236 Kurbelclub Chaos :: Vollgas Vierer :: Tischkampfarena Alte Platte
7246 * :: Die Rillenritter :: *
7256 Stangenhelden :: Die Griffbanditen :: Die Platte am Fluss
7266 Die Tischwölfe :: Stangenterror :: Gegenstoß-Galerie
7276 FC Gummipuffer :: Die Bandenkrieger :: Arena am Gleittisch
7286 Griff & Gloria :: Tischgewitter :: Schusshof Kurbeldorf
7297 FC Hartkurbel :: Stangenterror :: Drehkraft-Dome
7307 Die Griffbanditen :: * :: *
7317 Tischgewitter :: Die Tischwölfe :: Griffgipfel Arena
7327 Die Kugeljäger :: FC Gummipuffer :: Griffgipfel Arena
7337 Rotationssportverein :: Stangenhelden :: Drehkraft-Dome
7347 Die Rillenritter :: Die Bandenkrieger :: Kickerklotz Kolosseum
7357 Vollgas Vierer :: Die Schussscheiben :: Twistpark Westrand
7367 Griff & Gloria :: Kurbelclub Chaos :: Schusshof Kurbeldorf
7378 Stangenterror :: FC Gummipuffer :: Kugelwerk Ost
7388 Die Kugeljäger :: Die Griffbanditen :: Griffgipfel Arena
7398 Rotationssportverein :: Griff & Gloria :: Drehkraft-Dome
7408 Die Rillenritter :: Tischgewitter :: Kickerklotz Kolosseum
7418 Stangenhelden :: FC Hartkurbel :: Die Platte am Fluss
7428 * :: Vollgas Vierer :: *
7438 Die Tischwölfe :: Die Schussscheiben :: Kickerforum Süd
7448 Die Bandenkrieger :: Kurbelclub Chaos :: Griffzentrum Westkurve
7459 Stangenterror :: Griff & Gloria :: Kugelwerk Ost
7469 Die Griffbanditen :: FC Hartkurbel :: Haltepunkt Hohlgriff
7479 Tischgewitter :: Die Kugeljäger :: Griffgipfel Arena
7489 Die Schussscheiben :: Die Bandenkrieger :: Kickerklotz Kolosseum
7499 Kurbelclub Chaos :: Die Rillenritter :: Tischkampfarena Alte Platte
7509 Rotationssportverein :: Vollgas Vierer :: Drehkraft-Dome
7519 * :: Stangenhelden :: *
7529 FC Gummipuffer :: Die Tischwölfe :: Arena am Gleittisch
75310 FC Hartkurbel :: FC Gummipuffer :: Drehkraft-Dome
75410 * :: Tischgewitter :: *
75510 Kurbelclub Chaos :: Die Griffbanditen :: Tischkampfarena Alte Platte
75610 Rotationssportverein :: Die Kugeljäger :: Twistpark Westrand
75710 Die Rillenritter :: Stangenterror :: Kickerklotz Kolosseum
75810 Stangenhelden :: Die Schussscheiben :: Bandenbruch-Stadion
75910 Die Tischwölfe :: Griff & Gloria :: Gegenstoß-Galerie
76010 Die Bandenkrieger :: Vollgas Vierer :: Drehkraft-Dome
76111 Stangenterror :: * :: *
76211 Die Griffbanditen :: Die Bandenkrieger :: Haltepunkt Hohlgriff
76311 Die Schussscheiben :: Tischgewitter :: Kickerklotz Kolosseum
76411 Kurbelclub Chaos :: FC Hartkurbel :: Tischkampfarena Alte Platte
76511 Stangenhelden :: FC Gummipuffer :: Die Platte am Fluss
76611 Vollgas Vierer :: Die Kugeljäger :: Twistpark Westrand
76711 Die Tischwölfe :: Rotationssportverein :: Gegenstoß-Galerie
76811 Griff & Gloria :: Die Rillenritter :: Schusshof Kurbeldorf
76912 FC Hartkurbel :: Die Schussscheiben :: Schusshof Kurbeldorf
77012 Tischgewitter :: Kurbelclub Chaos :: Griffgipfel Arena
77112 Die Kugeljäger :: Stangenterror :: Griffgipfel Arena
77212 Rotationssportverein :: Die Griffbanditen :: Drehkraft-Dome
77312 Die Rillenritter :: Die Tischwölfe :: Kickerklotz Kolosseum
77412 Stangenhelden :: Griff & Gloria :: Die Platte am Fluss
77512 Die Bandenkrieger :: * :: *
77612 FC Gummipuffer :: Vollgas Vierer :: Arena am Gleittisch
77713 Die Griffbanditen :: Stangenterror :: Haltepunkt Hohlgriff
77813 Tischgewitter :: Stangenhelden :: Griffgipfel Arena
77913 Kurbelclub Chaos :: Die Schussscheiben :: Tischkampfarena Alte Platte
78013 Die Rillenritter :: Rotationssportverein :: Kickerklotz Kolosseum
78113 Vollgas Vierer :: FC Hartkurbel :: GegenstoĂź-Galerie
78213 Die Bandenkrieger :: Die Tischwölfe :: Drehkraft-Dome
78313 FC Gummipuffer :: * :: *
78413 Griff & Gloria :: Die Kugeljäger :: Schusshof Kurbeldorf
78514 FC Hartkurbel :: Tischgewitter :: Schusshof Kurbeldorf
78614 Die Kugeljäger :: * :: *
78714 Kurbelclub Chaos :: Rotationssportverein :: Tischkampfarena Alte Platte
78814 Die Rillenritter :: Vollgas Vierer :: Kickerklotz Kolosseum
78914 Stangenhelden :: Stangenterror :: Die Platte am Fluss
79014 Die Tischwölfe :: Die Griffbanditen :: Gegenstoß-Galerie
79114 FC Gummipuffer :: Die Schussscheiben :: Schusshof Kurbeldorf
79214 Griff & Gloria :: Die Bandenkrieger :: Drehkraft-Dome
79315 Stangenterror :: FC Hartkurbel :: Kugelwerk Ost
79415 Die Griffbanditen :: Die Tischwölfe :: Haltepunkt Hohlgriff
79515 Die Schussscheiben :: * :: *
79615 Rotationssportverein :: Die Bandenkrieger :: Drehkraft-Dome
79715 Die Rillenritter :: Griff & Gloria :: Kickerklotz Kolosseum
79815 Stangenhelden :: Kurbelclub Chaos :: Bandenbruch-Stadion
79915 Vollgas Vierer :: Tischgewitter :: Twistpark Westrand
80015 FC Gummipuffer :: Die Kugeljäger :: Schusshof Kurbeldorf
80116 FC Hartkurbel :: Kurbelclub Chaos :: Schusshof Kurbeldorf
80216 Tischgewitter :: Die Griffbanditen :: Griffgipfel Arena
80316 Die Kugeljäger :: Die Rillenritter :: Griffgipfel Arena
80416 Rotationssportverein :: Die Schussscheiben :: Twistpark Westrand
80516 Stangenhelden :: * :: *
80616 Vollgas Vierer :: FC Gummipuffer :: GegenstoĂź-Galerie
80716 Die Tischwölfe :: Die Bandenkrieger :: Gegenstoß-Galerie
80816 Griff & Gloria :: Stangenterror :: Drehkraft-Dome
80917 Stangenterror :: Die Tischwölfe :: Kugelwerk Ost
81017 * :: FC Hartkurbel :: *
81117 Die Kugeljäger :: Die Schussscheiben :: Griffgipfel Arena
81217 Die Rillenritter :: Kurbelclub Chaos :: Kickerklotz Kolosseum
81317 Vollgas Vierer :: Die Griffbanditen :: GegenstoĂź-Galerie
81417 Die Bandenkrieger :: Stangenhelden :: Drehkraft-Dome
81517 FC Gummipuffer :: Tischgewitter :: Schusshof Kurbeldorf
81617 Griff & Gloria :: Rotationssportverein :: Drehkraft-Dome
81718 Tischgewitter :: FC Hartkurbel :: Griffgipfel Arena
81818 Die Schussscheiben :: Die Griffbanditen :: Kickerklotz Kolosseum
81918 Kurbelclub Chaos :: FC Gummipuffer :: Tischkampfarena Alte Platte
82018 Rotationssportverein :: Die Rillenritter :: Twistpark Westrand
82118 Vollgas Vierer :: Stangenterror :: GegenstoĂź-Galerie
82218 Die Tischwölfe :: Die Kugeljäger :: Kickerforum Süd
82318 * :: Die Bandenkrieger :: *
82418 Griff & Gloria :: Stangenhelden :: Drehkraft-Dome
82519 FC Hartkurbel :: Vollgas Vierer :: Drehkraft-Dome
82619 * :: Die Griffbanditen :: *
82719 Die Schussscheiben :: Griff & Gloria :: Kickerklotz Kolosseum
82819 Kurbelclub Chaos :: Die Kugeljäger :: Tischkampfarena Alte Platte
82919 Rotationssportverein :: Tischgewitter :: Twistpark Westrand
83019 Stangenhelden :: Die Tischwölfe :: Die Platte am Fluss
83119 Die Bandenkrieger :: Stangenterror :: Drehkraft-Dome
83219 FC Gummipuffer :: Die Rillenritter :: Schusshof Kurbeldorf
83320 Stangenterror :: Kurbelclub Chaos :: Twistground Central
83420 FC Hartkurbel :: Stangenhelden :: Drehkraft-Dome
83520 Die Griffbanditen :: Griff & Gloria :: Haltepunkt Hohlgriff
83620 Tischgewitter :: Die Bandenkrieger :: Griffgipfel Arena
83720 Die Schussscheiben :: FC Gummipuffer :: Kickerklotz Kolosseum
83820 * :: Die Kugeljäger :: *
83920 Vollgas Vierer :: Rotationssportverein :: GegenstoĂź-Galerie
84020 Die Tischwölfe :: Die Rillenritter :: Kickerforum Süd
84121 FC Hartkurbel :: Die Rillenritter :: Schusshof Kurbeldorf
84221 Tischgewitter :: Griff & Gloria :: Griffgipfel Arena
84321 Die Schussscheiben :: Stangenterror :: Kickerklotz Kolosseum
84421 Die Kugeljäger :: Die Bandenkrieger :: Griffgipfel Arena
84521 Kurbelclub Chaos :: * :: *
84621 Rotationssportverein :: Die Tischwölfe :: Drehkraft-Dome
84721 Stangenhelden :: Vollgas Vierer :: Die Platte am Fluss
84821 FC Gummipuffer :: Die Griffbanditen :: Arena am Gleittisch
84922 Stangenterror :: Tischgewitter :: Twistground Central
85022 FC Hartkurbel :: Die Griffbanditen :: Drehkraft-Dome
85122 Die Schussscheiben :: Die Tischwölfe :: Kickerklotz Kolosseum
85222 Rotationssportverein :: FC Gummipuffer :: Drehkraft-Dome
85322 Die Rillenritter :: * :: *
85422 Stangenhelden :: Die Kugeljäger :: Bandenbruch-Stadion
85522 Vollgas Vierer :: Kurbelclub Chaos :: Twistpark Westrand
85622 Die Bandenkrieger :: Griff & Gloria :: Drehkraft-Dome
85723 FC Hartkurbel :: Die Kugeljäger :: Schusshof Kurbeldorf
85823 Die Griffbanditen :: Die Rillenritter :: Schusshof Kurbeldorf
85923 Tischgewitter :: * :: *
86023 Die Schussscheiben :: Stangenhelden :: Kickerklotz Kolosseum
86123 Kurbelclub Chaos :: Griff & Gloria :: Tischkampfarena Alte Platte
86223 Rotationssportverein :: Stangenterror :: Drehkraft-Dome
86323 Die Tischwölfe :: Vollgas Vierer :: Gegenstoß-Galerie
86423 Die Bandenkrieger :: FC Gummipuffer :: Drehkraft-Dome
86524 Die Griffbanditen :: Stangenhelden :: Haltepunkt Hohlgriff
86624 Die Schussscheiben :: Kurbelclub Chaos :: Kickerklotz Kolosseum
86724 Die Kugeljäger :: Vollgas Vierer :: Griffgipfel Arena
86824 * :: Rotationssportverein :: *
86924 Die Tischwölfe :: Tischgewitter :: Kickerforum Süd
87024 Die Bandenkrieger :: Die Rillenritter :: Griffzentrum Westkurve
87124 FC Gummipuffer :: Stangenterror :: Arena am Gleittisch
87224 Griff & Gloria :: FC Hartkurbel :: Drehkraft-Dome
87325 Stangenterror :: Stangenhelden :: Kugelwerk Ost
87425 FC Hartkurbel :: Die Tischwölfe :: Drehkraft-Dome
87525 Die Griffbanditen :: Rotationssportverein :: Haltepunkt Hohlgriff
87625 Die Kugeljäger :: Griff & Gloria :: Griffgipfel Arena
87725 Kurbelclub Chaos :: Tischgewitter :: Tischkampfarena Alte Platte
87825 Die Rillenritter :: Die Schussscheiben :: Kickerklotz Kolosseum
87925 Vollgas Vierer :: Die Bandenkrieger :: GegenstoĂź-Galerie
88025 * :: FC Gummipuffer :: *
88126 * :: Stangenterror :: *
88226 Tischgewitter :: Die Rillenritter :: Griffgipfel Arena
88326 Die Schussscheiben :: FC Hartkurbel :: Kickerklotz Kolosseum
88426 Die Kugeljäger :: Rotationssportverein :: Griffgipfel Arena
88526 Die Tischwölfe :: Kurbelclub Chaos :: Kickerforum Süd
88626 Die Bandenkrieger :: Die Griffbanditen :: Drehkraft-Dome
88726 FC Gummipuffer :: Stangenhelden :: Arena am Gleittisch
88826 Griff & Gloria :: Vollgas Vierer :: Drehkraft-Dome
88927 Stangenterror :: Die Rillenritter :: Twistground Central
89027 FC Hartkurbel :: Rotationssportverein :: Drehkraft-Dome
89127 Die Griffbanditen :: Die Kugeljäger :: Schusshof Kurbeldorf
89227 Die Schussscheiben :: Vollgas Vierer :: Kickerklotz Kolosseum
89327 Kurbelclub Chaos :: Die Bandenkrieger :: Tischkampfarena Alte Platte
89427 Stangenhelden :: Tischgewitter :: Bandenbruch-Stadion
89527 * :: Die Tischwölfe :: *
89627 FC Gummipuffer :: Griff & Gloria :: Arena am Gleittisch
89728 Stangenterror :: Die Kugeljäger :: Twistground Central
89828 Die Griffbanditen :: Kurbelclub Chaos :: Schusshof Kurbeldorf
89928 Tischgewitter :: Die Schussscheiben :: Griffgipfel Arena
90028 Stangenhelden :: Rotationssportverein :: Die Platte am Fluss
90128 Vollgas Vierer :: Die Rillenritter :: Twistpark Westrand
90228 Die Tischwölfe :: FC Gummipuffer :: Gegenstoß-Galerie
90328 Die Bandenkrieger :: FC Hartkurbel :: Drehkraft-Dome
90428 Griff & Gloria :: * :: *
90529 Stangenterror :: Die Griffbanditen :: Kugelwerk Ost
90629 Die Kugeljäger :: Tischgewitter :: Griffgipfel Arena
90729 Rotationssportverein :: Kurbelclub Chaos :: Twistpark Westrand
90829 Die Rillenritter :: Stangenhelden :: Kickerklotz Kolosseum
90929 Vollgas Vierer :: * :: *
91029 Die Bandenkrieger :: Die Schussscheiben :: Griffzentrum Westkurve
91129 FC Gummipuffer :: FC Hartkurbel :: Arena am Gleittisch
91229 Griff & Gloria :: Die Tischwölfe :: Drehkraft-Dome
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..298723e
--- /dev/null
+++ b/index.html
@@ -0,0 +1,13 @@
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title>Tabula Rasa</title>
6 <link rel="stylesheet" href="style.css">
7 <script src="csp.js"></script>
8 <script src="tabularasa.js" defer></script>
9 </head>
10 <body>
11 <div id="anchor" />
12 </body>
13</html>
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..4adfed0
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
ortools
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..47d2d84
--- /dev/null
+++ b/style.css
@@ -0,0 +1,21 @@
1body {
2 font-family: "HelveticaNeueLight", "HelveticaNeue-Light", "Helvetica Neue Light", "HelveticaNeue", "Helvetica Neue", "TeXGyreHerosRegular", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif; font-weight:400; font-stretch:normal;
3}
4
5table {
6 border-collapse: collapse;
7 margin: 25px 0;
8 font-size: 0.9em;
9 font-family: sans-serif;
10 min-width: 50%;
11 max-width: 50%;
12 box-sizing: border-box;
13}
14
15thead {
16 position: sticky;
17 top: 0px;
18 background-color: Canvas;
19 text-align: left;
20}
21
diff --git a/tabularasa.js b/tabularasa.js
new file mode 100644
index 0000000..ee45493
--- /dev/null
+++ b/tabularasa.js
@@ -0,0 +1,284 @@
1// let API = "http://localhost:8080/example.json";
2let API = "example.json";
3
4var tabelle = [] /* Will contain all pairings */
5var leagues = [] /* List of league ids */
6var max_spieltage = 0;
7var next_pairing_id = 0;
8
9function weekday_to_string(weekday) {
10 return new Date(Date.UTC(1970, 0, 6+weekday)).toLocaleDateString(undefined, { weekday: 'long' });
11}
12
13var wildcard = JSON.parse('{"id":"-1", "name":"*"}');
14var nowhere = JSON.parse('{"id":"-1", "name":"*"}');
15
16class paarung {
17 static _next_id = 0;
18 constructor(team_a, team_b, league, ort) {
19 this.id = next_pairing_id++;
20 this.team_a = team_a;
21 this.team_b = team_b;
22 this.league = league;
23 this.ort = ort;
24 }
25
26 get weekday() {
27 if (this.team_a.id != -1 && this.team_b.id != -1)
28 return weekday_to_string(this.team_a.tag);
29 return "*";
30 }
31
32 get spieltag() {
33 if (!this.spieltage.size)
34 return -1;
35 return [...this.spieltage][0];
36 }
37
38 get name() {
39 return this.team_a.name + " :: " + this.team_b.name + ", Liga " + this.league;
40 }
41};
42
43function is_same(team_a, team_b) {
44 if (team_a.id == -1 || team_b.id == -1 || team_a.id != team_b.id)
45 return false;
46 return true;
47}
48
49function is_same_ort(ort_a, ort_b) {
50 if (ort_a.id == -1 || ort_b.id == -1 || ort_a.id != ort_b.id)
51 return false;
52 return true;
53}
54
55function createTextElement(name, text) {
56 let elem = document.createElement(name);
57 elem.appendChild(document.createTextNode(text));
58 return elem;
59}
60
61function appendChildList(elem, name, ...texts) {
62 for (const text of texts)
63 elem.appendChild(createTextElement(name, text));
64}
65
66function draw_table() {
67 /* Draw tables for each league */
68 let anchor = document.getElementById("anchor");
69 for (league of leagues) {
70 anchor.appendChild(createTextElement("h2", "Liga " + league.toString()));
71
72 let table = document.createElement("table");
73 let thead = document.createElement("thead");
74 let tr = document.createElement("tr");
75 appendChildList(tr, "th", "Heim", "Gäste", "Wochentag", "Tisch", "Spieltag");
76 thead.appendChild(tr);
77 table.appendChild(thead);
78
79 for (paar of tabelle.filter(paar => paar.league == league).sort((paar_a, paar_b) => { if (!paar_a.spieltage.size || !paar_b.spieltage.size) return -1; return paar_a.spieltag - paar_b.spieltag } )) {
80 let tr = document.createElement("tr");
81 appendChildList(tr, "td", paar.team_a.name, paar.team_b.name, paar.weekday, paar.ort.name, 1 + paar.spieltag);
82
83 table.appendChild(tr);
84 }
85 anchor.appendChild(table);
86 }
87}
88
89function fill_table(data) {
90 leagues = [...new Set(data.teams.map(team => team.liga))].sort();
91
92 /* Init some objects */
93 for (ort of data.orte)
94 ort.pairings = new Array();
95
96 /* Count necessary spieltage */
97 for (league of leagues) {
98 let pairings_count = data.teams.filter(team => team.liga == league).sort((a,b) => a.id > b.id).length;
99 if (pairings_count % 2)
100 pairings_count++;
101 max_spieltage = Math.max(2 * (pairings_count - 1), max_spieltage);
102 }
103
104 /* Fill out complete table for all leagues */
105 for (league of leagues) {
106 let league_teams = data.teams.filter(team => team.liga == league).sort((a,b) => a.id > b.id);
107 console.log( "liga " + league_teams.length );
108
109 for (team_a of league_teams) {
110 var game_count = 0;
111 for (team_b of league_teams) {
112 if (team_a == team_b)
113 continue;
114
115 /* If Heimspiel-Team is smokers and the Gastteam is not, the alternative
116 location needs to be chosen */
117 var ort = data.orte.find(ort => ort.id == team_a.heimort);
118 if (team_b.nichtraucher && ort.raucher)
119 ort = data.orte.find(ort => ort.id == team_a.ersatzort);
120
121 pair = new paarung(team_a, team_b, league, ort);
122 tabelle.push(pair);
123 ort.pairings.push(pair);
124 game_count++;
125 }
126 /* Fill rest of this team's games with wildcard games */
127 while (game_count < max_spieltage / 2) {
128 tabelle.push(new paarung(team_a, wildcard, league, nowhere));
129 tabelle.push(new paarung(wildcard, team_a, league, nowhere));
130 game_count++;
131 }
132 }
133 }
134
135 /* Fill all leagues with uneven or fewer spieltage with wildcard games */
136 for (league of leagues) {
137
138 }
139
140 /* Check if an ort is over-provisioned
141 for (ort of data.orte) {
142 for (weekday of [...new Set(ort.pairings.map(pair => pair.weekday))].sort()) {
143 var games_on_day = ort.pairings.filter(pair => pair.weekday = weekday);
144 if (games_on_day > max_spieltage)
145 alert("Ort " + ort.name + "over provisioned on weekday " + weekday_to_string(weekday));
146 }
147 } */
148}
149
150function shuffle_array(array) {
151 return array.map(value => ({ value, sort: Math.random() }))
152 .sort((a, b) => a.sort - b.sort)
153 .map(({ value }) => value);
154}
155
156function not_equal_function(s1, s2) { return s1 != s2; }
157
158function find_csp_solution() {
159 var all_spieltage = new Array();
160 for (let i=0; i < max_spieltage; i++)
161 all_spieltage.push(i);
162
163 for (league of leagues) {
164 var sub = tabelle.filter(paar => paar.league == league);
165 var candidate = {}, variables = {}, constraints = [];
166 for (outer of sub) {
167 variables[outer.id] = [...all_spieltage];
168 for (inner of tabelle.filter(inner =>
169 inner.id > outer.id && (
170 is_same(outer.team_a, inner.team_a) ||
171 is_same(outer.team_b, inner.team_a) ||
172 is_same(outer.team_a, inner.team_b) ||
173 is_same(outer.team_b, inner.team_b))))
174 {
175 constraints.push([outer.id, inner.id, not_equal_function]);
176 }
177 }
178
179 candidate.variables = variables;
180 candidate.constraints = constraints;
181
182 var result = csp.solve(candidate);
183 console.log(result);
184 }
185}
186
187
188function find_table_configuration() {
189 /* Check if there is one possible configuration that fulfills the following criteria:
190 1) each team must have 0 or 1 games on any given week
191 2) each location+weekday combo must have 0 or 1 games on any given week
192 3) each pairing needs a week and a location
193 */
194 var candidates = tabelle; /* Take a copy of the array */
195
196 /* Add all possible spieltage to the list for
197 them to be later reduced */
198 for (paar of candidates) {
199 paar.spieltage = new Set();
200 for (let i=0; i < max_spieltage; i++)
201 paar.spieltage.add(i);
202 }
203
204 /* TODO: Add more initial constraints */
205
206 while (candidates.length) {
207 /* First pick the pairings that have the least amount of spieltage to fit in */
208 candidates = shuffle_array(candidates).sort((a, b) => a.spieltage.size <= b.spieltage.size);
209
210 var looking_at = candidates.pop();
211
212 /* Pick random spieltag out of the possible ones */
213 let spieltag = Array.from(looking_at.spieltage)[Math.floor(Math.random() * looking_at.spieltage.size)];
214
215 /* Now we have to remove all new conflicting dates from other unset pairings: */
216
217 /* Filter out all pairings on the same spieltag with the current team */
218 for (paar of candidates.filter(paar =>
219 is_same(paar.team_a, looking_at.team_a) ||
220 is_same(paar.team_b, looking_at.team_a) ||
221 is_same(paar.team_a, looking_at.team_b) ||
222 is_same(paar.team_b, looking_at.team_b)))
223 {
224 paar.spieltage.delete(spieltag);
225 }
226
227 /* Filter out all pairing on the same spieltag with the same ort and weekday
228 for (paar of candidates.filter(paar =>
229 is_same_ort(paar.ort, looking_at.ort) &&
230 paar.weekday == looking_at.weekday))
231 {
232 if (paar.ort.id != -1 && looking_at.ort.id != -1)
233 paar.spieltage.delete(spieltag);
234 }
235 */
236
237 /* Filter out the reverse pairing until the second half of the season (Rueckrunde).
238 If it doesn't exist, we're probably already in Rueckrunde
239 var runden_start = Math.floor(max_spieltage * Math.floor(spieltag * 2 / max_spieltage) / 2);
240 for (paar of candidates.filter(paar =>
241 is_same(paar.team_a, looking_at.team_b) ||
242 is_same(paar.team_b, looking_at.team_a))) {
243 for (var exclude = 0; exclude < max_spieltage / 2; exclude++)
244 paar.spieltage.delete(runden_start + exclude);
245 }
246*/
247 /* Filter out home rounds for the home team on next spieltag and guest rounds for
248 guest team on next spieltag, except for end of Hinrunde
249 if (spieltag != max_spieltage / 2 - 1)
250 for (paar of candidates.filter(paar =>
251 is_same(paar.team_a, looking_at.team_a) ||
252 is_same(paar.team_b, looking_at.team_b)))
253 paar.spieltage.delete(spieltag + 1);
254*/
255
256 for (paar of candidates)
257 if (paar.spieltage.size == 0) {
258 console.log(candidates.length);
259 return false;
260 }
261
262 /* Now fix the date */
263 looking_at.spieltage = new Set();
264 looking_at.spieltage.add(spieltag);
265 }
266 return true;
267}
268
269function init() {
270 var xhttp = new XMLHttpRequest();
271 xhttp.onreadystatechange = function() {
272 if (this.readyState == 4 && this.status == 200) {
273 fill_table(xhttp.response);
274 //find_table_configuration();
275 find_csp_solution();
276 draw_table();
277 }
278 };
279 xhttp.responseType = "json";
280 xhttp.open("GET", API, true);
281 xhttp.send();
282}
283
284init();