├── .gitignore ├── LICENSE ├── README.md ├── manage.py ├── noq ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py ├── views.py └── wsgi.py ├── solvers ├── __init__.py ├── akari.py ├── aqre.py ├── aquapelago.py ├── aquarium.py ├── balanceloop.py ├── battleship.py ├── binairo.py ├── castlewall.py ├── cave.py ├── chocobanana.py ├── chocona.py ├── clasp.exe ├── countryroad.py ├── doppelblock.py ├── easyas.py ├── fillomino.py ├── gokigen.py ├── haisu.py ├── haisuslow.py ├── hamle.py ├── hashi.py ├── heteromino.py ├── heyawake.py ├── hitori.py ├── hotaru.py ├── kakuro.py ├── kuromasu.py ├── kurotto.py ├── lits.py ├── magnets.py ├── masyu.py ├── minesweeper.py ├── moonsun.py ├── nagare.py ├── nanro.py ├── ncells.py ├── nonogram.py ├── norinori.py ├── numberlink.py ├── nuribou.py ├── nurikabe.py ├── nurimisaki.py ├── onsen.py ├── rippleeffect.py ├── shakashaka.py ├── shikaku.py ├── shimaguni.py ├── skyscrapers.py ├── slitherlink.py ├── spiralgalaxies.py ├── starbattle.py ├── statuepark.py ├── stostone.py ├── sudoku.py ├── tapa.py ├── tatamibari.py ├── tents.py ├── tll.py ├── tren.py ├── utils │ ├── README.md │ ├── __init__.py │ ├── borders.py │ ├── encoding.py │ ├── grids.py │ ├── loops.py │ ├── numbers.py │ ├── regions.py │ ├── shading.py │ ├── shapes.py │ └── solutions.py ├── yajilin.py ├── yajisankazusan.py └── yinyang.py ├── static ├── admin │ ├── css │ │ ├── autocomplete.css │ │ ├── base.css │ │ ├── changelists.css │ │ ├── dashboard.css │ │ ├── fonts.css │ │ ├── forms.css │ │ ├── login.css │ │ ├── nav_sidebar.css │ │ ├── responsive.css │ │ ├── responsive_rtl.css │ │ ├── rtl.css │ │ ├── vendor │ │ │ └── select2 │ │ │ │ ├── LICENSE-SELECT2.md │ │ │ │ ├── select2.css │ │ │ │ └── select2.min.css │ │ └── widgets.css │ ├── fonts │ │ ├── LICENSE.txt │ │ ├── README.txt │ │ ├── Roboto-Bold-webfont.woff │ │ ├── Roboto-Light-webfont.woff │ │ └── Roboto-Regular-webfont.woff │ ├── img │ │ ├── LICENSE │ │ ├── README.txt │ │ ├── calendar-icons.svg │ │ ├── gis │ │ │ ├── move_vertex_off.svg │ │ │ └── move_vertex_on.svg │ │ ├── icon-addlink.svg │ │ ├── icon-alert.svg │ │ ├── icon-calendar.svg │ │ ├── icon-changelink.svg │ │ ├── icon-clock.svg │ │ ├── icon-deletelink.svg │ │ ├── icon-no.svg │ │ ├── icon-unknown-alt.svg │ │ ├── icon-unknown.svg │ │ ├── icon-viewlink.svg │ │ ├── icon-yes.svg │ │ ├── inline-delete.svg │ │ ├── search.svg │ │ ├── selector-icons.svg │ │ ├── sorting-icons.svg │ │ ├── tooltag-add.svg │ │ └── tooltag-arrowright.svg │ └── js │ │ ├── SelectBox.js │ │ ├── SelectFilter2.js │ │ ├── actions.js │ │ ├── actions.min.js │ │ ├── admin │ │ ├── DateTimeShortcuts.js │ │ └── RelatedObjectLookups.js │ │ ├── autocomplete.js │ │ ├── calendar.js │ │ ├── cancel.js │ │ ├── change_form.js │ │ ├── collapse.js │ │ ├── collapse.min.js │ │ ├── core.js │ │ ├── inlines.js │ │ ├── inlines.min.js │ │ ├── jquery.init.js │ │ ├── nav_sidebar.js │ │ ├── popup_response.js │ │ ├── prepopulate.js │ │ ├── prepopulate.min.js │ │ ├── prepopulate_init.js │ │ ├── timeparse.js │ │ ├── urlify.js │ │ └── vendor │ │ ├── jquery │ │ ├── LICENSE.txt │ │ ├── jquery.js │ │ └── jquery.min.js │ │ ├── select2 │ │ ├── LICENSE.md │ │ ├── i18n │ │ │ ├── af.js │ │ │ ├── ar.js │ │ │ ├── az.js │ │ │ ├── bg.js │ │ │ ├── bn.js │ │ │ ├── bs.js │ │ │ ├── ca.js │ │ │ ├── cs.js │ │ │ ├── da.js │ │ │ ├── de.js │ │ │ ├── dsb.js │ │ │ ├── el.js │ │ │ ├── en.js │ │ │ ├── es.js │ │ │ ├── et.js │ │ │ ├── eu.js │ │ │ ├── fa.js │ │ │ ├── fi.js │ │ │ ├── fr.js │ │ │ ├── gl.js │ │ │ ├── he.js │ │ │ ├── hi.js │ │ │ ├── hr.js │ │ │ ├── hsb.js │ │ │ ├── hu.js │ │ │ ├── hy.js │ │ │ ├── id.js │ │ │ ├── is.js │ │ │ ├── it.js │ │ │ ├── ja.js │ │ │ ├── ka.js │ │ │ ├── km.js │ │ │ ├── ko.js │ │ │ ├── lt.js │ │ │ ├── lv.js │ │ │ ├── mk.js │ │ │ ├── ms.js │ │ │ ├── nb.js │ │ │ ├── ne.js │ │ │ ├── nl.js │ │ │ ├── pl.js │ │ │ ├── ps.js │ │ │ ├── pt-BR.js │ │ │ ├── pt.js │ │ │ ├── ro.js │ │ │ ├── ru.js │ │ │ ├── sk.js │ │ │ ├── sl.js │ │ │ ├── sq.js │ │ │ ├── sr-Cyrl.js │ │ │ ├── sr.js │ │ │ ├── sv.js │ │ │ ├── th.js │ │ │ ├── tk.js │ │ │ ├── tr.js │ │ │ ├── uk.js │ │ │ ├── vi.js │ │ │ ├── zh-CN.js │ │ │ └── zh-TW.js │ │ ├── select2.full.js │ │ └── select2.full.min.js │ │ └── xregexp │ │ ├── LICENSE.txt │ │ ├── xregexp.js │ │ └── xregexp.min.js ├── all_pages.py ├── consts.py ├── jquery.js ├── mathjax-import.js ├── noq │ ├── data.js │ ├── elves.js │ ├── images │ │ ├── +.png │ │ ├── +x.png │ │ ├── -.png │ │ ├── -b.png │ │ ├── 1.png │ │ ├── 1b.png │ │ ├── 7.png │ │ ├── 7b.png │ │ ├── =.png │ │ ├── J.png │ │ ├── Jb.png │ │ ├── L.png │ │ ├── Lb.png │ │ ├── battleship_bottom_end.png │ │ ├── battleship_left_end.png │ │ ├── battleship_right_end.png │ │ ├── battleship_top_end.png │ │ ├── battleship_water.png │ │ ├── bl.png │ │ ├── black.png │ │ ├── black_circle.png │ │ ├── bottom-left.png │ │ ├── bottom-right.png │ │ ├── bottom_end.png │ │ ├── br.png │ │ ├── brbl.png │ │ ├── bulb.png │ │ ├── center_dot.png │ │ ├── down_arrow.png │ │ ├── e.png │ │ ├── large_black_circle.png │ │ ├── left_arrow.png │ │ ├── left_end.png │ │ ├── moon.png │ │ ├── n.png │ │ ├── ne.png │ │ ├── negative_wide_down_arrow.png │ │ ├── negative_wide_left_arrow.png │ │ ├── negative_wide_right_arrow.png │ │ ├── negative_wide_up_arrow.png │ │ ├── nw.png │ │ ├── r.png │ │ ├── rb.png │ │ ├── right_arrow.png │ │ ├── right_end.png │ │ ├── s.png │ │ ├── se.png │ │ ├── sw.png │ │ ├── tent.png │ │ ├── tl.png │ │ ├── tlbl.png │ │ ├── tlbr.png │ │ ├── tlbrbl.png │ │ ├── tltr.png │ │ ├── tltrbl.png │ │ ├── tltrbr.png │ │ ├── tltrbrbl.png │ │ ├── top-left.png │ │ ├── top-right.png │ │ ├── top_end.png │ │ ├── tr.png │ │ ├── trbl.png │ │ ├── trbr.png │ │ ├── trbrbl.png │ │ ├── tree.png │ │ ├── unused │ │ │ ├── +w.png │ │ │ ├── -w.png │ │ │ ├── 1w.png │ │ │ ├── 7w.png │ │ │ ├── Jw.png │ │ │ ├── Lo.png │ │ │ └── rw.png │ │ ├── up_arrow.png │ │ ├── w.png │ │ ├── white_circle.png │ │ ├── white_circle_d.png │ │ ├── white_circle_l.png │ │ ├── white_circle_r.png │ │ ├── white_circle_u.png │ │ ├── wide_down_arrow.png │ │ ├── wide_left_arrow.png │ │ ├── wide_right_arrow.png │ │ ├── wide_up_arrow.png │ │ ├── ‖.png │ │ ├── ←.png │ │ ├── ←b.png │ │ ├── ↑.png │ │ ├── ↑b.png │ │ ├── →.png │ │ ├── →b.png │ │ ├── ↓.png │ │ ├── ↓b.png │ │ ├── ↰.png │ │ ├── ↱.png │ │ ├── ↲.png │ │ ├── ↳.png │ │ ├── ↴.png │ │ ├── ⬏.png │ │ ├── ⬐.png │ │ └── ⬑.png │ ├── imps.js │ ├── noq.css │ ├── noq.js │ └── noq_recycle_bin.txt ├── style.css └── utils.py ├── templates ├── base.html ├── index.html └── noq.html └── test ├── README.md ├── __init__.py └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | **/__pycache__/ 2 | *.pyc 3 | clasp.exe 4 | clasp 5 | *~ 6 | noq/settings.py 7 | **/claspy.py 8 | **/migrations/ 9 | db.sqlite3 10 | **/static/consts.py 11 | .DS_Store 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Noq 2 | 3 | This repo contains source code for Noq, an automated logic puzzle solver for use in constructing or solving puzzles. 4 | 5 | Noq is currently accessible on the web at [noq.solutions](https://www.noq.solutions/), formerly at [mstang.xyz/noq](https://www.mstang.xyz/noq). It is powered by Django and runs on a PythonAnywhere web server. 6 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'noq.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /noq/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/noq/__init__.py -------------------------------------------------------------------------------- /noq/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for noq project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'noq.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /noq/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | from . import views 4 | from .views import urlpatterns 5 | 6 | # urlpatterns is defined in views.py automatically now (5/6/20) -------------------------------------------------------------------------------- /noq/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.http import * 3 | from django.template import Template, RequestContext, Context 4 | from django.urls import include, path 5 | from django.views.generic.base import RedirectView 6 | from django.contrib import admin 7 | import traceback 8 | import json 9 | from static import utils 10 | from static.consts import types as PUZZLE_TYPES, cats as CATS 11 | 12 | def create_view(pt_dict): 13 | return lambda request: render(request, './noq.html', pt_dict) 14 | 15 | def redirect_view(red_url): 16 | return RedirectView.as_view(url=red_url) 17 | 18 | urlpatterns = [] 19 | 20 | # index page 21 | 22 | types_by_cat = {} 23 | 24 | for pt_dict in PUZZLE_TYPES: 25 | cat = pt_dict['cat'] 26 | if cat not in types_by_cat: 27 | types_by_cat[cat] = [] 28 | types_by_cat[cat].append(pt_dict) 29 | 30 | for cat in types_by_cat: 31 | types_by_cat[cat] = sorted(types_by_cat[cat], key=lambda d: d['name']) 32 | 33 | urlpatterns.append( 34 | path(route='', 35 | view=lambda request: 36 | render(request, './index.html', {'types': types_by_cat, 'cats': CATS})) 37 | ) 38 | 39 | # solver pages 40 | 41 | for pt_dict in PUZZLE_TYPES: 42 | value = pt_dict['value'] 43 | name = pt_dict['name'] 44 | 45 | urlpatterns.append( 46 | path(route=value, view=create_view(pt_dict), name=f'{name} solver - Noq') 47 | ) 48 | 49 | if 'aliases' in pt_dict: 50 | for alias in pt_dict['aliases']: 51 | urlpatterns.append( 52 | path(route=alias, view=redirect_view(pt_dict['value'])) 53 | ) 54 | 55 | # internal/custom views 56 | 57 | from solvers import * 58 | from solvers.claspy import * 59 | 60 | def solver(request): 61 | try: 62 | reset() 63 | module = globals()[request.GET['puzzle_type']] 64 | puzzle_encoding = module.encode(request.GET['puzzle']) 65 | solutions_encoded = module.solve(puzzle_encoding) 66 | solutions_decoded = module.decode(solutions_encoded) 67 | return HttpResponse(solutions_decoded) 68 | # show error messages 69 | except ValueError as err: 70 | print(traceback.print_exc(),flush=True) 71 | return HttpResponseBadRequest(json.dumps({ 72 | 'message': str(err) 73 | })) 74 | except Exception as exc: 75 | print(traceback.print_exc(),flush=True) 76 | return HttpResponseServerError(json.dumps({ 77 | 'message': str(exc) 78 | })) 79 | 80 | # append internal urlpatterns 81 | urlpatterns += [ 82 | path('admin/', admin.site.urls), 83 | path('solver', solver, name='solver'), 84 | ] -------------------------------------------------------------------------------- /noq/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for noq project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'noq.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /solvers/__init__.py: -------------------------------------------------------------------------------- 1 | from os.path import dirname, basename, isfile, join 2 | import glob 3 | 4 | modules = glob.glob(join(dirname(__file__), '*.py')) 5 | submodules = [basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')] 6 | for submodule in submodules: 7 | exec(f'import solvers.{submodule}') -------------------------------------------------------------------------------- /solvers/akari.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.solutions import * 4 | 5 | def encode(string): 6 | return utils.encode(string, clue_encoder = lambda s : s) 7 | 8 | def solve(E): 9 | # BoolVar that is True iff (r,c) has a lightbulb 10 | bools = [[BoolVar() for c in range(E.C)] for r in range(E.R)] 11 | 12 | # ENFORCE THAT BLACK CELLS CAN'T HAVE LIGHTBULBS 13 | for (r,c) in E.clues: 14 | require(~bools[r][c]) 15 | 16 | # ENFORCE THAT NUMBERED CLUES ARE CORRECT 17 | for (r,c) in E.clues: 18 | if E.clues[(r,c)].isnumeric(): 19 | # require that contents[(r,c)] equals the number 20 | # of true BoolVars for the (up to four) adjacent cells 21 | require(sum_bools(int(E.clues[(r,c)]), 22 | [ bools[r+dr][c+dc] for (dr,dc) in ((0,1),(1,0),(0,-1),(-1,0)) 23 | if 0 <= r+dr < E.R and 0 <= c+dc < E.C ])) 24 | 25 | # ENFORCE THAT EVERY CELL IS LIT UP, 26 | # AND THAT NO TWO LIGHTBULBS SEE EACH OTHER 27 | for r in range(E.R): 28 | for c in range(E.C): 29 | if (r,c) not in E.clues: 30 | # get all other cells from which (r,c) might be lit up 31 | visible_cells = [] 32 | for (dr,dc) in (0,1),(1,0),(0,-1),(-1,0): 33 | i = 1 34 | while True: 35 | r1, c1 = r+i*dr, c+i*dc 36 | if 0 <= r1 < E.R and 0 <= c1 < E.C and (r1,c1) not in E.clues: 37 | visible_cells.append((r1,c1)) 38 | else: 39 | break 40 | i += 1 41 | # now, either (r,c) has a lightbulb and none of visible_cells does, 42 | # or (r,c) doesn't have a lightbulb and at least one of visible_cells does 43 | require(bools[r][c] != at_least(1, [bools[x][y] for (x,y) in visible_cells])) 44 | 45 | return get_all_grid_solutions(bools, 46 | format_function = lambda r, c: 'bulb.png' if bools[r][c].value() else '') 47 | 48 | def decode(solutions): 49 | return utils.decode(solutions) 50 | -------------------------------------------------------------------------------- /solvers/aqre.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string, has_borders=True) 6 | 7 | def solve(E): 8 | set_max_val(E.R*E.C) 9 | 10 | shading_solver = utils.RectangularGridShadingSolver(E.R,E.C) 11 | shading_solver.black_connectivity() 12 | grid = shading_solver.grid 13 | 14 | # GIVEN NUMBERS ARE SATISFIED 15 | if E.clues: 16 | for coord in (clue_regions := utils.full_bfs(E.R, E.C, E.edge_ids, clues=E.clues)): 17 | require(sum_bools(E.clues[coord], [grid[other] for other in clue_regions[coord]])) 18 | 19 | # NO FOUR IN A ROW 20 | for i in range(E.R): 21 | for j in range(E.C): 22 | if i list of possible clues that could end up at this cell 9 | # (each clue is identified by its coordinate pair) 10 | possible_values = {} 11 | for (clue, val) in E.clues.items(): 12 | r, c = clue 13 | for new_loc in [(r+val, c), (r-val, c), (r, c-val), (r, c+val)]: 14 | if is_valid_coord(E.r, E.c, *new_loc): 15 | possible_values[new_loc] = possible_values.get(new_loc, []) + [clue] 16 | 17 | # grid: cell -> ID of clue that is moved there, or None 18 | grid = RectangularGrid(E.r, E.c, 19 | lambda r, c: MultiVar(None, *possible_values.get((r,c), [])) 20 | ) 21 | 22 | # require that each clue gets moved to exactly one new location 23 | for (clue, val) in E.clues.items(): 24 | r, c = clue 25 | 26 | conds = [] 27 | for new_loc in [(r+val, c), (r-val, c), (r, c-val), (r, c+val)]: 28 | if is_valid_coord(E.r, E.c, *new_loc): 29 | conds.append(grid[new_loc] == clue) 30 | require(sum_bools(1, conds), clue) 31 | 32 | # convert grid to shading to check adjacency and connectivity conditions 33 | binary_grid = RectangularGridShadingSolver(E.r, E.c) 34 | for cell in grid.iter_coords(): 35 | require(binary_grid.grid[cell] == (grid[cell] != None)) 36 | require(binary_grid.no_adjacent()) 37 | require(binary_grid.white_connectivity()) 38 | 39 | return get_all_grid_solutions( 40 | grid, 41 | format_function = lambda r, c: E.clues.get(grid[(r,c)].value(), "white") 42 | ) -------------------------------------------------------------------------------- /solvers/heyawake.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils import borders 4 | from .utils.borders import Direction 5 | 6 | def encode(string): 7 | return utils.encode(string, has_borders = True) 8 | 9 | def solve(E): 10 | rooms = utils.regions.full_bfs(E.R, E.C, E.edges, E.clues) 11 | 12 | shading_solver = utils.RectangularGridShadingSolver(E.R, E.C) 13 | shading_solver.no_adjacent() 14 | shading_solver.white_connectivity() 15 | region_solver = utils.RectangularGridRegionSolver(E.R, E.C, 16 | shading_solver.grid, given_regions = rooms) 17 | region_solver.set_shaded_cells_in_region(E.clues, [True]) 18 | 19 | for r in range(E.R): 20 | borders_in_row = [c for c in range(1,E.C) if (r,c,Direction.LEFT) in E.edges] 21 | # for each pair of consecutive borders, we get a constraint: 22 | # at least one cell in this span has to be shaded 23 | for i in range(len(borders_in_row)-1): 24 | b1, b2 = borders_in_row[i], borders_in_row[i+1] 25 | x = BoolVar(False) 26 | for c in range(b1-1,b2+1): 27 | x |= shading_solver.grid[r][c] 28 | require(x) 29 | 30 | for c in range(E.C): 31 | borders_in_col = [r for r in range(1,E.R) if (r,c,Direction.TOP) in E.edges] 32 | for i in range(len(borders_in_col)-1): 33 | b1, b2 = borders_in_col[i], borders_in_col[i+1] 34 | x = BoolVar(False) 35 | for r in range(b1-1,b2+1): 36 | x |= shading_solver.grid[r][c] 37 | require(x) 38 | 39 | return shading_solver.solutions(shaded_color = 'darkgray') 40 | 41 | def decode(solutions): 42 | return utils.decode(solutions) -------------------------------------------------------------------------------- /solvers/hitori.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.shading import * 4 | 5 | def encode(string): 6 | return utils.encode(string) 7 | 8 | def solve(E): 9 | set_max_val(max(E.R, E.C)) 10 | s = RectangularGridShadingSolver(E.R, E.C) 11 | 12 | K = list(E.clues.keys()) 13 | for i, (r,c) in enumerate(K): 14 | for (r1,c1) in K[i+1:]: 15 | if E.clues[(r,c)] == E.clues[(r1,c1)] and (r == r1 or c == c1): 16 | require(s.grid[r][c] | s.grid[r1][c1]) 17 | s.no_adjacent() 18 | s.white_connectivity() 19 | 20 | return s.solutions() 21 | 22 | 23 | def decode(solutions): 24 | return utils.decode(solutions) -------------------------------------------------------------------------------- /solvers/kakuro.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.solutions import * 4 | 5 | def encode(string): 6 | return utils.encode(string) 7 | 8 | def solve(E): 9 | # Find sections and their corresponding clues 10 | # Maintain a list of tuples (sum, [(r1, c1), (r2, c2), ...]). 11 | # 'sum' is 0 when the clue is blank; this is because we need to 12 | # check every run for duplicates. 13 | sums = [] 14 | 15 | def end_run(start_coord, coords, idx): 16 | if start_coord in E.clues: 17 | value = E.clues[start_coord] 18 | if len(coords) > 0: 19 | if value == 'black': 20 | sums.append((0, coords)) 21 | else: 22 | sums.append((value[idx], coords)) 23 | elif value != 'black' and value[idx] != 0: 24 | return False 25 | else: 26 | sums.append((0, coords)) 27 | return True 28 | 29 | # Across sections 30 | for r in range(E.R): 31 | start_coord = (r, -1) 32 | coords = [] 33 | for c in range(E.C): 34 | if (r, c) in E.clues: 35 | if not end_run(start_coord, coords, 0): 36 | return [] 37 | start_coord = (r, c) 38 | coords = [] 39 | else: 40 | coords.append((r,c)) 41 | end_run(start_coord, coords, 0) 42 | # Down sections 43 | for c in range(E.C): 44 | start_coord = (-1, c) 45 | coords = [] 46 | for r in range(E.R): 47 | if (r, c) in E.clues: 48 | if not end_run(start_coord, coords, 1): 49 | return [] 50 | start_coord = (r, c) 51 | coords = [] 52 | else: 53 | coords.append((r,c)) 54 | end_run(start_coord, coords, 1) 55 | 56 | # Solve the puzzle! 57 | grid = [[IntVar(0, 9) for c in range(E.C)] for r in range(E.R)] 58 | 59 | for sum_clue, coord_list in sums: 60 | intvars = [grid[r][c] for (r, c) in coord_list] 61 | if sum_clue: 62 | require(sum_clue == sum(intvars)) 63 | if len(intvars) > 1: # require_all_diff throws an error if there's only 1 item 64 | require_all_diff(intvars) 65 | 66 | for r in range(E.R): 67 | for c in range(E.C): 68 | require((grid[r][c] == 0) == ((r,c) in E.clues)) 69 | 70 | return get_all_grid_solutions(grid, 71 | format_function = lambda r, c: grid[r][c].value() if grid[r][c].value() else '') 72 | 73 | def decode(solutions): 74 | return utils.decode(solutions) 75 | -------------------------------------------------------------------------------- /solvers/kuromasu.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string) 6 | 7 | def solve(E): 8 | set_max_val(E.R*E.C) 9 | 10 | s = utils.RectangularGridShadingSolver(E.R,E.C) 11 | arbitrary_white_clue = None # Use this later 12 | 13 | # Steal code from Cave 14 | for ((r,c), value) in E.clues.items(): 15 | arbitrary_white_clue = (r,c) 16 | if value == '?': 17 | continue 18 | dirs = {} 19 | for (u,v) in ((1,0),(-1,0),(0,1),(0,-1)): 20 | ray = [] 21 | n = 1 22 | while 0 <= r+u*n < E.R and 0 <= c+v*n < E.C: # add all ray cells 23 | ray.append((r+u*n,c+v*n)) 24 | n += 1 25 | num_seen_cells = IntVar(0, len(ray)) 26 | for n in range(len(ray)+1): 27 | cond_n = BoolVar(True) 28 | for d in range(n): 29 | cond_n &= (~s.grid[ray[d]]) 30 | if n < len(ray): 31 | cond_n &= s.grid[ray[n]] 32 | require((num_seen_cells == n) == cond_n) 33 | dirs[(u,v)] = num_seen_cells 34 | require(dirs[(1,0)]+dirs[(-1,0)]+dirs[(0,1)]+dirs[(0,-1)] == E.clues[(r,c)]-1) 35 | 36 | # Simple rules 37 | s.white_connectivity(arbitrary_white_clue) 38 | s.no_adjacent() 39 | s.white_clues(E.clues) 40 | 41 | return s.solutions() 42 | 43 | def decode(solutions): 44 | return utils.decode(solutions) 45 | -------------------------------------------------------------------------------- /solvers/kurotto.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | import time 4 | 5 | def encode(string): 6 | return utils.encode(string) 7 | 8 | def solve(E): 9 | set_max_val(E.R*E.C) 10 | 11 | shading_solver = utils.RectangularGridShadingSolver(E.R,E.C) 12 | 13 | for (r,c) in E.clues: 14 | require(~shading_solver.grid[(r,c)]) 15 | 16 | anchors = [coord for coord in E.clues if E.clues[coord] != 'black'] 17 | # 'black' means an empty circle in this case; sorry, I'm being lazy with the encoding 18 | 19 | for anchor in anchors: 20 | flows = utils.RectangularGrid(E.R, E.C, lambda: Atom()) 21 | flows[anchor].prove_if(True) # prove the anchor for free 22 | 23 | for r in range(E.R): 24 | for c in range(E.C): 25 | for (dr,dc) in [(0,1),(0,-1),(1,0),(-1,0)]: 26 | r1 = r + dr 27 | c1 = c + dc 28 | if 0 <= r1 < E.R and 0 <= c1 < E.C: 29 | if (r1,c1) == anchor: 30 | flows[r][c].prove_if(shading_solver.grid[r][c]) 31 | else: 32 | flows[r][c].prove_if(shading_solver.grid[r][c] & 33 | shading_solver.grid[r1][c1] & flows[r1][c1]) 34 | 35 | require(sum_bools(E.clues[anchor]+1, 36 | [flows[r][c] for r in range(E.R) for c in range(E.C)])) 37 | # add 1 because the clue cell is proven but not black 38 | 39 | return shading_solver.solutions(shaded_color = 'black') 40 | 41 | def decode(solutions): 42 | return utils.decode(solutions) 43 | -------------------------------------------------------------------------------- /solvers/magnets.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils import borders 4 | 5 | def encode(string): 6 | return utils.encode(string, has_borders = True, outside_clues = '1111') 7 | 8 | def solve(E): 9 | rooms = utils.regions.full_bfs(E.R, E.C, E.edges) 10 | 11 | for room in rooms: 12 | if len(room) != 2: 13 | raise ValueError('All regions must be of size 2.') 14 | 15 | set_max_val(3) 16 | grid = utils.RectangularGrid(E.R, E.C, lambda : MultiVar('+', '-', ' ')) 17 | 18 | # Require that the number of +s is equal to the number of -s; so either there's one of each or none 19 | for room in rooms: 20 | require( 21 | sum_vars([grid[r][c] == '+' for (r, c) in room]) == sum_vars([grid[r][c] == '-' for (r, c) in room]) 22 | ) 23 | 24 | # Require neighbor conditions 25 | for r in range(E.R): 26 | for c in range(E.C): 27 | require( 28 | # None of the neighbors have the same value as this, or this is blank (neighbors can be anything) 29 | (sum_bools(0, [(grid[y][x] == grid[r][c]) for (y, x) in grid.get_neighbors(r, c)]) | 30 | (grid[r][c] == ' ')) 31 | ) 32 | 33 | # Require correctness of + (top and left) clues 34 | for c in E.top: 35 | require(sum_bools(E.top[c], [(grid[r][c] == '+') for r in range(E.R)])) 36 | for r in E.left: 37 | require(sum_bools(E.left[r], [(grid[r][c] == '+') for c in range(E.C)])) 38 | 39 | # Require correctness of - (bottom and right) clues 40 | for c in E.bottom: 41 | require(sum_bools(E.bottom[c], [(grid[r][c] == '-') for r in range(E.R)])) 42 | for r in E.right: 43 | require(sum_bools(E.right[r], [(grid[r][c] == '-') for c in range(E.C)])) 44 | 45 | return utils.solutions.get_all_grid_solutions(grid) 46 | 47 | def decode(solutions): 48 | return utils.decode(solutions) -------------------------------------------------------------------------------- /solvers/minesweeper.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string) 6 | 7 | def solve(E): 8 | set_max_val(8) 9 | shading_solver = utils.RectangularGridShadingSolver(E.R,E.C) 10 | 11 | # Enforce that clue cells can't be shaded, and that their numbers are correct 12 | shading_solver.white_clues(E.clues) 13 | 14 | for (cell, num) in E.clues.items(): 15 | if num != '?': 16 | require(sum_bools(num, [ 17 | shading_solver.grid[surr] 18 | for surr in shading_solver.grid.get_surroundings(*cell) 19 | ])) 20 | 21 | return shading_solver.solutions() 22 | 23 | def decode(solutions): 24 | return utils.decode(solutions) -------------------------------------------------------------------------------- /solvers/moonsun.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.borders import * 4 | from .utils.loops import * 5 | from .utils.regions import * 6 | 7 | def encode(string): 8 | return utils.encode(string, clue_encoder = lambda s : s, has_borders = True) 9 | 10 | def solve(E): 11 | loop_solver = utils.RectangularGridLoopSolver(E.R, E.C) 12 | rooms = full_bfs(E.R, E.C, E.edges) 13 | region_type = [[MultiVar('m', 's') for r in range(E.R)] for c in range(E.C)] 14 | 15 | # In each room, either: 16 | # - hit all moons + no suns 17 | # - hit all suns + no moons 18 | for room in rooms: 19 | has_moons, has_suns = False, False 20 | hit_all_moons, hit_all_suns = BoolVar(True), BoolVar(True) 21 | hit_at_least_1_moon, hit_at_least_1_sun = BoolVar(False), BoolVar(False) 22 | for (r, c) in room: 23 | if (r, c) in E.clues: 24 | is_nonempty = loop_solver.grid[r][c] != '' 25 | if E.clues[(r, c)] == 'm': 26 | has_moons = True 27 | hit_all_moons &= is_nonempty 28 | hit_at_least_1_moon |= is_nonempty 29 | require(is_nonempty == (region_type[r][c] == 'm')) 30 | elif E.clues[(r, c)] == 's': 31 | has_suns = True 32 | hit_all_suns &= is_nonempty 33 | hit_at_least_1_sun |= is_nonempty 34 | require(is_nonempty == (region_type[r][c] == 's')) 35 | if not (has_moons or has_suns): 36 | raise ValueError('Every region must contain at least 1 moon or sun.') 37 | require(sum_bools(1, [has_moons & hit_all_moons, has_suns & hit_all_suns])) 38 | require(sum_bools(1, [hit_at_least_1_moon, hit_at_least_1_sun])) 39 | 40 | # Make sure that each region is marked correctly as an m or s region 41 | for r in range(1, E.R): 42 | for c in range(E.C): 43 | require((region_type[r-1][c] == region_type[r][c]) | ((r, c, Direction.TOP) in E.edges)) 44 | require((region_type[r-1][c] != region_type[r][c]) | 45 | ~(var_in(loop_solver.grid[r][c], UP_CONNECTING) & ((r, c, Direction.TOP) in E.edges))) 46 | for r in range(E.R): 47 | for c in range(1, E.C): 48 | require((region_type[r][c-1] == region_type[r][c]) | ((r, c, Direction.LEFT) in E.edges)) 49 | require((region_type[r][c-1] != region_type[r][c]) | 50 | ~(var_in(loop_solver.grid[r][c], LEFT_CONNECTING) & ((r, c, Direction.LEFT) in E.edges))) 51 | 52 | # Basic rules 53 | loop_solver.loop({}) 54 | loop_solver.no_reentrance(rooms) 55 | loop_solver.hit_every_region(rooms) 56 | 57 | return loop_solver.solutions() 58 | 59 | def decode(solutions): 60 | return utils.decode(solutions) 61 | -------------------------------------------------------------------------------- /solvers/nanro.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | def clue_encoder(s): 6 | try: 7 | return utils.default_clue_encoder(s) 8 | except RuntimeError: 9 | if s[0] == 's' and s[1:].isnumeric(): # signpost clue 10 | return s 11 | else: 12 | raise RuntimeError('Invalid input, still') 13 | 14 | E = utils.encode(string, clue_encoder = clue_encoder, has_borders = True) 15 | 16 | # separate signpost clues from regular clues 17 | new_clues = {} 18 | E.signpost_clues = {} 19 | for key in E.clues: 20 | s = E.clues[key] 21 | if type(s) == str and s[0] == 's' and s[1:].isnumeric(): # signpost clue 22 | E.signpost_clues[key] = int(s[1:]) 23 | else: 24 | new_clues[key] = s 25 | E.clues = new_clues 26 | return E 27 | 28 | def solve(E): 29 | rooms = utils.regions.full_bfs(E.R, E.C, E.edges) 30 | 31 | # note: not the largest clue value! not every region has a clue in it, 32 | # so a big region could require more unshaded cells than the largest clue. 33 | set_max_val(max(len(room) for room in rooms)) 34 | 35 | shading_solver = utils.RectangularGridShadingSolver(E.R, E.C) 36 | region_solver = utils.RectangularGridRegionSolver(E.R, E.C, shading_solver.grid, rooms) 37 | 38 | shading_solver.white_clues(E.clues) 39 | shading_solver.white_connectivity() 40 | shading_solver.no_white_2x2() 41 | 42 | region_solver.set_unshaded_cells_in_region(E.clues, [True]) 43 | 44 | # require each region to have at least one numbered cell 45 | for region in rooms: 46 | require(at_least(1, [~shading_solver.grid[r][c] for (r, c) in region])) 47 | 48 | # require signpost clues to be true 49 | for region in rooms: 50 | for cell in region: 51 | if cell in E.signpost_clues: 52 | require(sum_bools(E.signpost_clues[cell], [~shading_solver.grid[p] for p in region])) 53 | 54 | for r in range(E.R): 55 | for c in range(E.C): 56 | unshaded_count = region_solver.get_unshaded_cells_in_region(r, c, [True]) 57 | neighbors = region_solver.get_neighbors_in_other_regions(r, c) 58 | # white cells that are next to each other and in different regions 59 | # cannot have the same number in them 60 | require(sum_bools(0, [ 61 | (~shading_solver.grid[r][c] & 62 | ~shading_solver.grid[y][x] & 63 | (unshaded_count == region_solver.get_unshaded_cells_in_region(y, x, [True])) 64 | ) for (y, x) in neighbors 65 | ])) 66 | 67 | def format_function(r, c): 68 | unshaded_count = region_solver.get_unshaded_cells_in_region(r, c, [True]) 69 | return 'darkgray' if shading_solver.grid[r][c].value() else unshaded_count.value() 70 | 71 | return utils.get_all_grid_solutions(shading_solver.grid, format_function = format_function) 72 | 73 | def decode(solutions): 74 | return utils.decode(solutions) 75 | -------------------------------------------------------------------------------- /solvers/ncells.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string, has_params = True) 6 | 7 | def solve(E): 8 | region_size = int(E.params['region_size']) 9 | 10 | assert (E.R * E.C) % region_size == 0, "It's impossible to divide grid into regions of this size!" 11 | 12 | # set the maximum IntVar value to the number of cells 13 | set_max_val(E.R*E.C) 14 | 15 | region_solver = utils.RectangularGridRegionSolver(E.R, E.C, max_num_regions = E.R*E.C) 16 | border_solver = utils.RectangularGridBorderSolver(E.R, E.C, region_solver) 17 | 18 | region_solver.set_region_size(region_size, [], min_region_size = region_size) 19 | region_solver.region_roots({}) 20 | 21 | for (r, c) in E.clues: 22 | region_solver.set_num_neighbors_in_different_region(r, c, E.clues[(r,c)]) 23 | 24 | return border_solver.solutions() 25 | 26 | def decode(solutions): 27 | return utils.decode(solutions) 28 | -------------------------------------------------------------------------------- /solvers/norinori.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string, has_borders = True) 6 | 7 | def solve(E): 8 | set_max_val(2) 9 | 10 | s = utils.shading.RectangularGridShadingSolver(E.R, E.C) 11 | regions = utils.regions.full_bfs(E.R, E.C, E.edges) 12 | 13 | # Nori rules 14 | for r in range(E.R): 15 | for c in range(E.C): 16 | # If shaded, then 17 | require( 18 | # Exactly 1 neighbor is shaded 19 | sum_bools(1, [s.grid[y][x] for (y, x) in utils.grids.get_neighbors(E.R, E.C, r, c)]) | 20 | ~s.grid[r][c] 21 | ) 22 | 23 | # Region clues 24 | for region in regions: 25 | require(sum_bools(2, [s.grid[r][c] for (r, c) in region])) 26 | 27 | return s.solutions(shaded_color = 'darkgray') 28 | 29 | def decode(solutions): 30 | return utils.decode(solutions) 31 | -------------------------------------------------------------------------------- /solvers/nurikabe.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string) 6 | 7 | def solve(E): 8 | # Reduce IntVar size by counting clue cells and assigning each one an id. 9 | clue_cell_id = {} 10 | number_clues = {} 11 | has_nonnumber_clue = False 12 | for r in range(E.R): 13 | for c in range(E.C): 14 | if (r, c) in E.clues: 15 | clue_cell_id[(r,c)] = len(clue_cell_id) 16 | value = E.clues[(r,c)] 17 | if value == '?': 18 | has_nonnumber_clue = True 19 | else: 20 | number_clues[(r,c)] = value 21 | max_clue = (E.R*E.C - sum(number_clues.values())) if has_nonnumber_clue else \ 22 | (max(number_clues.values()) if number_clues else 0) 23 | 24 | if len(clue_cell_id) == 0: 25 | raise ValueError('Error: No clues') 26 | 27 | # Restrict the number of bits used for IntVar. 28 | set_max_val(max(len(clue_cell_id), max_clue)) 29 | 30 | shading_solver = utils.RectangularGridShadingSolver(E.R, E.C) 31 | shading_solver.black_connectivity() 32 | shading_solver.no_black_2x2() 33 | 34 | region_solver = utils.RectangularGridRegionSolver(E.R, E.C, shading_solver.grid, 35 | max_num_regions = len(clue_cell_id), region_symbol_sets = [[False,]]) 36 | region_solver.region_roots(clue_cell_id, exact = True) 37 | region_solver.set_region_size(max_clue, number_clues, clue_region_bijection = not has_nonnumber_clue) 38 | 39 | return shading_solver.solutions() 40 | 41 | def decode(solutions): 42 | return utils.decode(solutions) 43 | -------------------------------------------------------------------------------- /solvers/nurimisaki.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.shading import * 4 | 5 | def encode(string): 6 | return utils.encode(string) 7 | 8 | def solve(E): 9 | set_max_val(E.R*E.C) 10 | 11 | s = RectangularGridShadingSolver(E.R, E.C) 12 | arbitrary_white_clue = None # Use this later 13 | # Steal #-seen-cells logic from Cave 14 | for ((r,c), value) in E.clues.items(): 15 | arbitrary_white_clue = (r,c) 16 | if value == '?': 17 | continue 18 | dirs = {} 19 | for (u,v) in ((1,0),(-1,0),(0,1),(0,-1)): 20 | ray = [] 21 | n = 1 22 | while 0 <= r+u*n < E.R and 0 <= c+v*n < E.C: # add all ray cells 23 | ray.append((r+u*n,c+v*n)) 24 | n += 1 25 | num_seen_cells = IntVar(0, len(ray)) 26 | for n in range(len(ray)+1): 27 | cond_n = BoolVar(True) 28 | for d in range(n): 29 | cond_n &= (~s.grid[ray[d]]) 30 | if n < len(ray): 31 | cond_n &= s.grid[ray[n]] 32 | require((num_seen_cells == n) == cond_n) 33 | dirs[(u,v)] = num_seen_cells 34 | require(dirs[(1,0)]+dirs[(-1,0)]+dirs[(0,1)]+dirs[(0,-1)] == E.clues[(r,c)]-1) 35 | # A white cell can see in exactly 1 of the directions iff it is specially indicated 36 | for r in range(E.R): 37 | for c in range(E.C): 38 | if (r,c) in E.clues: 39 | require(sum_bools(1, [~s.grid[y][x] for (y,x) in s.grid.get_neighbors(r,c)])) 40 | else: 41 | require(at_least(2, [~s.grid[y][x] for (y,x) in s.grid.get_neighbors(r,c)]) 42 | | s.grid[r][c]) 43 | # Simple rules 44 | s.white_clues(E.clues) 45 | s.white_connectivity(known_root = arbitrary_white_clue) 46 | s.no_black_2x2() 47 | s.no_white_2x2() 48 | return s.solutions() 49 | 50 | def decode(solutions): 51 | return utils.decode(solutions) 52 | -------------------------------------------------------------------------------- /solvers/onsen.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string, has_borders = True) 6 | 7 | def solve(E): 8 | rooms = utils.regions.full_bfs(E.R, E.C, E.edges) 9 | 10 | if len(E.clues) == 0: 11 | raise ValueError('There are no clues!') 12 | 13 | # get the size of the largest room 14 | max_room_size = max(len(room) for room in rooms) 15 | 16 | # set the value of the "max clue" (largest number of loop cells that can be within any region) 17 | max_clue = 1 18 | for clue in E.clues.values(): 19 | max_clue = max(max_clue, clue) if clue != '?' else max_room_size 20 | 21 | # set the maximum IntVar value to the largest of: 22 | # - greatest clue value (determines number of cells in a region that are part of a loop) 23 | # - number of clue cells (determines number of loop IDs) 24 | set_max_val(max(len(E.clues), max_clue)) 25 | 26 | # create a dictionary mapping each clue to its required path length (which is an int (given) or IntVar(0, max_clue) for ?s) 27 | clue_to_path_length = {(r, c): E.clues[(r, c)] if E.clues[(r, c)] != '?' else IntVar(0, max_clue) for (r, c) in E.clues} 28 | 29 | # give each clue cell its own loop ID 30 | loop_ids = {} 31 | for r in range(E.R): 32 | for c in range(E.C): 33 | if (r, c) in E.clues: 34 | loop_ids[(r,c)] = len(loop_ids) 35 | 36 | loop_solver = utils.RectangularGridLoopSolver(E.R, E.C, 37 | min_num_loops = len(E.clues), max_num_loops = len(E.clues)) 38 | loop_solver.loop(E.clues, includes_clues = True) 39 | loop_solver.no_reentrance(rooms) 40 | loop_solver.hit_every_region(rooms) 41 | 42 | # set the loop IDs of the clue cells (these are our "anchors") 43 | for (r, c) in E.clues: 44 | require(loop_solver.loop_id[r][c] == loop_ids[(r,c)]) 45 | 46 | # require that each loop has the correct number of cells in a room 47 | for room in rooms: 48 | for loop_id in range(len(E.clues)): 49 | # get the corresponding clue number 50 | for (r, c) in E.clues: 51 | if loop_ids[(r,c)] == loop_id: 52 | clue_num = clue_to_path_length[(r,c)] 53 | path_length = sum_vars([loop_solver.loop_id[r][c] == loop_id for (r, c) in room]) 54 | require((path_length == 0) | (path_length == clue_num)) 55 | 56 | return loop_solver.solutions() 57 | 58 | def decode(solutions): 59 | return utils.decode(solutions) 60 | -------------------------------------------------------------------------------- /solvers/rippleeffect.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string, has_borders = True) 6 | 7 | def solve(E): 8 | rooms = utils.regions.full_bfs(E.R, E.C, E.edges) 9 | 10 | # set the maximum IntVar value to be the max room size 11 | max_room_size = max(len(room) for room in rooms) 12 | set_max_val(max_room_size) 13 | 14 | grid = [[IntVar(1, max_room_size) for c in range(E.C)] for r in range(E.R)] 15 | 16 | # Require that each room has exactly the numbers 1 through (room size), inclusive. 17 | for room in rooms: 18 | for i in range(1, len(room)+1): 19 | require(sum_bools(1, [grid[r][c] == i for (r, c) in room])) 20 | 21 | for r in range(E.R): 22 | for c in range(E.C): 23 | for i in range(1, max_room_size+1): 24 | # If the cell at this position has value i, 25 | # make sure that the next i cells in the row don't have this value 26 | require(sum_bools(0, [grid[r][c] == grid[r][x] for x in range(c+1, min(c+1+i, E.C))]) | 27 | (grid[r][c] != i)) 28 | 29 | for c in range(E.C): 30 | for r in range(E.R): 31 | for i in range(1, max_room_size+1): 32 | # See above, but for columns. 33 | require(sum_bools(0, [grid[r][c] == grid[y][c] for y in range(r+1, min(r+1+i, E.R))]) | 34 | (grid[r][c] != i)) 35 | 36 | # If there are any numbers given in the grid, make sure they're the same in the solution. 37 | for (r,c) in E.clues: 38 | require(grid[r][c] == E.clues[(r,c)]) 39 | 40 | return utils.get_all_grid_solutions(grid) 41 | 42 | def decode(solutions): 43 | return utils.decode(solutions) 44 | -------------------------------------------------------------------------------- /solvers/shikaku.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.solutions import * 4 | 5 | def encode(string): 6 | return utils.encode(string) 7 | 8 | class Box(object): 9 | ''' 10 | A box whose borders (inclusive) are given by top, bottom, left, & right. 11 | e.g. Box(0, 2, 1, 3) would make a 3x3 box with upper left is at (0, 1) & lower right at (2, 3) 12 | ''' 13 | def __init__(self, top, bottom, left, right): 14 | self.top = top 15 | self.bottom = bottom 16 | self.left = left 17 | self.right = right 18 | 19 | def solve(E): 20 | if len(E.clues) == 0: 21 | raise ValueError('Please provide at least one clue.') 22 | 23 | rs = utils.RectangularGridRegionSolver(E.R, E.C, max_num_regions = len(E.clues)) 24 | 25 | # Assign each clue to an ID (bijection, by puzzle rules) 26 | clue_to_id = {} 27 | for (r, c) in E.clues: 28 | require(rs.region_id[r][c] == len(clue_to_id)) 29 | clue_to_id[(r, c)] = len(clue_to_id) 30 | 31 | # Assign each clue to a Box 32 | clue_to_box = {} 33 | for (r, c) in E.clues: 34 | box = Box(IntVar(0, E.R-1), IntVar(0, E.R-1), IntVar(0, E.C-1), IntVar(0, E.C-1)) 35 | clue_to_box[(r, c)] = box 36 | # Rectangle size constraints from clues 37 | # Factor pairs are "ordered" (i.e. (a, b) and (b, a) will both be present if a != b) 38 | if E.clues[(r,c)] != '?': 39 | possible_dims = utils.numbers.factor_pairs(E.clues[(r, c)]) 40 | dim_constraint = BoolVar(False) 41 | for (a, b) in possible_dims: 42 | # Add, don't subtract, just to be safe 43 | # Eqivalent to box.bottom - box.top + 1 == a, & similar for L/R 44 | dim_constraint |= ((box.top + a == box.bottom + 1) & (box.left + b == box.right + 1)) 45 | require(dim_constraint) 46 | 47 | # Assign region IDs based on Box corners 48 | for r in range(E.R): 49 | for c in range(E.C): 50 | for (x, y) in E.clues: 51 | box = clue_to_box[(x, y)] 52 | require(((box.top <= r) & (r <= box.bottom) & (box.left <= c) & (c <= box.right)) == \ 53 | (rs.region_id[r][c] == clue_to_id[(x, y)])) 54 | 55 | return rs.solutions() 56 | 57 | 58 | def decode(solutions): 59 | return utils.decode(solutions) 60 | -------------------------------------------------------------------------------- /solvers/skyscrapers.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils import encoding 4 | 5 | def encode(string): 6 | return utils.encode(string, outside_clues = '1111') 7 | 8 | def solve(E): 9 | if E.R != E.C: 10 | raise ValueError('Skyscrapers puzzles must be square :(') 11 | n = E.R 12 | 13 | set_max_val(n) 14 | 15 | numbers_solver = utils.RectangularGridNumbersSolver(n, n, 1, n) 16 | numbers_solver.rows_and_cols() 17 | grid = numbers_solver.grid 18 | 19 | # given numbers 20 | for (i,j) in E.clues: 21 | if E.clues[(i,j)] == '?': 22 | continue 23 | require(grid[i][j] == E.clues[(i,j)]) 24 | 25 | # top clues 26 | top_visible = [[BoolVar(True) for c in range(n)] for r in range(n)] 27 | for i in range(n): 28 | for j in range(n): 29 | for k in range(i): 30 | top_visible[i][j] &= (grid[i][j] > grid[k][j]) 31 | for j in E.top: 32 | if E.top[j] == '?': 33 | continue 34 | require(sum_vars([top_visible[i][j] for i in range(n)]) == E.top[j]) 35 | 36 | # right clues 37 | right_visible = [[BoolVar(True) for c in range(n)] for r in range(n)] 38 | for i in range(n): 39 | for j in range(n): 40 | for k in range(j+1, n): 41 | right_visible[i][j] &= (grid[i][j] > grid[i][k]) 42 | for i in E.right: 43 | if E.right[i] == '?': 44 | continue 45 | require(sum_vars([right_visible[i][j] for j in range(n)]) == E.right[i]) 46 | 47 | # bottom clues 48 | bottom_visible = [[BoolVar(True) for c in range(n)] for r in range(n)] 49 | for i in range(n): 50 | for j in range(n): 51 | for k in range(i+1,n): 52 | bottom_visible[i][j] &= (grid[i][j] > grid[k][j]) 53 | for j in E.bottom: 54 | if E.bottom[j] == '?': 55 | continue 56 | require(sum_vars([bottom_visible[i][j] for i in range(n)]) == E.bottom[j]) 57 | 58 | # left clues 59 | left_visible = [[BoolVar(True) for c in range(n)] for r in range(n)] 60 | for i in range(n): 61 | for j in range(n): 62 | for k in range(j): 63 | left_visible[i][j] &= (grid[i][j] > grid[i][k]) 64 | for i in E.left: 65 | if E.left[i] == '?': 66 | continue 67 | require(sum_vars([left_visible[i][j] for j in range(n)]) == E.left[i]) 68 | 69 | return numbers_solver.solutions() 70 | 71 | def decode(solutions): 72 | return utils.decode(solutions) 73 | -------------------------------------------------------------------------------- /solvers/slitherlink.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string, clue_encoder = lambda s: s) 6 | 7 | def solve(E): 8 | number_clues, inside_clues, outside_clues = {}, set(), set() 9 | for clue, value in E.clues.items(): 10 | if value.isnumeric(): 11 | number_clues[clue] = int(value) 12 | elif value == 's': 13 | inside_clues.add(clue) 14 | elif value == 'w': 15 | outside_clues.add(clue) 16 | else: 17 | raise ValueError('Clues must be numbers, s, or w.') 18 | 19 | set_max_val(max(number_clues.values()) if number_clues else 0) 20 | 21 | bs = utils.RectangularGridBorderSolver(E.R, E.C) 22 | bs.loop() 23 | bs.clues(number_clues) 24 | bs.inside_loop(inside_clues) 25 | bs.outside_loop(outside_clues) 26 | return bs.solutions() 27 | 28 | def decode(solutions): 29 | return utils.decode(solutions) 30 | -------------------------------------------------------------------------------- /solvers/starbattle.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string, has_params = True, has_borders = True) 6 | 7 | def solve(E): 8 | num_stars = int(E.params['stars']) 9 | set_max_val(num_stars) 10 | 11 | rooms = utils.regions.full_bfs(E.R,E.C, E.edges) 12 | 13 | shading_solver = utils.RectangularGridShadingSolver(E.R,E.C) 14 | shading_solver.no_surrounding() 15 | 16 | for room in rooms: 17 | require(sum_bools(num_stars, [shading_solver.grid[r][c] for (r, c) in room])) 18 | 19 | for r in range(E.R): 20 | require(sum_bools(num_stars, [shading_solver.grid[r][c] for c in range(E.C)])) 21 | 22 | for c in range(E.C): 23 | require(sum_bools(num_stars, [shading_solver.grid[r][c] for r in range(E.R)])) 24 | 25 | return shading_solver.solutions(shaded_color = 'darkgray') 26 | 27 | def decode(solutions): 28 | return utils.decode(solutions) 29 | -------------------------------------------------------------------------------- /solvers/stostone.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.shading import * 4 | from .utils.regions import * 5 | 6 | def encode(string): 7 | return utils.encode(string, has_borders=True) 8 | 9 | def solve(E): 10 | if E.R % 2 != 0: 11 | raise ValueError('The stostone grid must have an even # rows.') 12 | 13 | max_stone_id = E.R//2 14 | set_max_val(max_stone_id) 15 | 16 | rooms = full_bfs(E.R, E.C, E.edges) 17 | rc_to_room, room_to_clue = {}, {} 18 | for room in rooms: 19 | for (r, c) in room: 20 | rc_to_room[(r,c)] = room 21 | if (r, c) in E.clues: 22 | room_to_clue[room] = int(E.clues[(r,c)]) 23 | 24 | s = RectangularGridShadingSolver(E.R, E.C) 25 | # Count number of black cells at a certain position and below in the same column. 26 | grid = [[IntVar(0, max_stone_id) for c in range(E.C)] for r in range(E.R)] 27 | 28 | # Black cells within a room must be connected. 29 | for room in rooms: 30 | chosen = {(r,c): BoolVar() for (r,c) in room} 31 | conns = [[Atom() for c in range(E.C)] for r in range(E.R)] 32 | for (r, c) in room: 33 | for (y, x) in get_neighbors(E.R, E.C, r, c): 34 | conns[r][c].prove_if((s.grid[y][x] & conns[y][x]) | chosen[(r,c)]) 35 | require(conns[r][c] | ~s.grid[r][c]) 36 | require(sum_bools(1, chosen.values())) 37 | 38 | # Cell with a number indicates number of black cells in region. 39 | # Or, if no number is present, >= 1 must be black. 40 | for room in rooms: 41 | if room in room_to_clue: 42 | require(sum_bools(room_to_clue[room], [s.grid[r][c] for (r, c) in room])) 43 | else: 44 | require(at_least(1, [s.grid[r][c] for (r, c) in room])) 45 | 46 | # When 2 cells are adjacent across region boundaries, at most 1 can be black. 47 | for r in range(E.R): 48 | for c in range(E.C): 49 | if r < E.R-1 and rc_to_room[(r,c)] != rc_to_room[(r+1,c)]: 50 | require(at_most(1, [s.grid[r][c], s.grid[r+1][c]])) 51 | if c < E.C-1 and rc_to_room[(r,c)] != rc_to_room[(r,c+1)]: 52 | require(at_most(1, [s.grid[r][c], s.grid[r][c+1]])) 53 | 54 | # Each column must have numbers 1 through max_stone_id. 55 | for c in range(E.C): 56 | require(grid[E.R-1][c] == cond(s.grid[E.R-1][c], 1, 0)) 57 | for r in range(E.R-2, -1, -1): 58 | require(grid[r][c] == (grid[r+1][c] + cond(s.grid[r][c], 1, 0))) 59 | require(grid[0][c] == max_stone_id) 60 | 61 | # Connected stones in different columns must fall together. 62 | for r in range(E.R): 63 | for c in range(E.C-1): 64 | require((grid[r][c] == grid[r][c+1]) | ~(s.grid[r][c] & s.grid[r][c+1])) 65 | 66 | return s.solutions(shaded_color='darkgray') 67 | 68 | def decode(solutions): 69 | return utils.decode(solutions) 70 | -------------------------------------------------------------------------------- /solvers/sudoku.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.solutions import * 4 | 5 | def encode(string): 6 | return utils.encode(string, has_params=True) 7 | 8 | def solve(E): 9 | def require_1_thru_n(arr): 10 | for i in range(1,n+1): 11 | require(at_least(1, [x==i for x in arr])) 12 | 13 | n = E.R 14 | set_max_val(n) 15 | 16 | grid = [[IntVar(1,n) for c in range(n)] for r in range(n)] 17 | 18 | # ENFORCE GIVENS ARE SATISFIED 19 | for (i,j) in E.clues: 20 | require(grid[i][j] == E.clues[(i,j)]) 21 | 22 | # ENFORCE ROWS, COLS ARE 1-n 23 | for i in range(n): 24 | require_1_thru_n([grid[i][j] for j in range(n)]) 25 | require_1_thru_n([grid[j][i] for j in range(n)]) 26 | 27 | # ENFORCE BOXES ARE 1-n 28 | m = int(n**0.5) 29 | for a in range(m): 30 | for b in range(m): 31 | require_1_thru_n([grid[m*a+i][m*b+j] for i in range(m) for j in range(m)]) 32 | 33 | if E.params['Diagonal']: # ENFORCE DIAGONALS ARE 1-n 34 | require_1_thru_n([grid[i][i] for i in range(n)]) 35 | require_1_thru_n([grid[i][8-i] for i in range(n)]) 36 | 37 | if E.params['Untouch']: # ENFORCE UNTOUCH RULE 38 | for i in range(n-1): 39 | for j in range(n-1): 40 | require(grid[i][j] != grid[i+1][j+1]) 41 | require(grid[i][j+1] != grid[i+1][j]) 42 | 43 | if E.params['Antiknight']: # ENFORCE ANTIKNIGHT RULE 44 | for i in range(n): 45 | for j in range(n): 46 | for (di,dj) in (2,-1), (1,-2), (-1,-2), (-2,-1): 47 | i0, j0 = i+di, j+dj 48 | if 0 <= i0 < n and 0 <= j0 < n: 49 | require(grid[i][j] != grid[i0][j0]) 50 | 51 | # antidiagonal, nonconsecutive 52 | # thermo, arrow, killer, consecutive-pairs [lambda in general] 53 | # add possibilities for a cell 54 | # and then don't forget to add instructions / explanation to the controls string 55 | 56 | return get_all_grid_solutions(grid) 57 | 58 | def decode(solutions): 59 | return utils.decode(solutions) 60 | -------------------------------------------------------------------------------- /solvers/tatamibari.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.solutions import * 4 | 5 | def encode(string): 6 | return utils.encode(string, clue_encoder = lambda s : s) 7 | 8 | class Box(object): 9 | ''' 10 | A box whose borders (inclusive) are given by top, bottom, left, & right. 11 | e.g. Box(0, 2, 1, 3) would make a 3x3 box with upper left is at (0, 1) & lower right at (2, 3) 12 | ''' 13 | def __init__(self, top, bottom, left, right): 14 | self.top = top 15 | self.bottom = bottom 16 | self.left = left 17 | self.right = right 18 | 19 | def solve(E): 20 | # Pre-processing. Necessary to filter out invalid clues. 21 | # Assign each clue to an ID (bijection, by puzzle rules) 22 | clue_to_id = {} 23 | for (r, c), value in E.clues.items(): 24 | if value in '+|-': 25 | clue_to_id[(r, c)] = len(clue_to_id) 26 | else: 27 | raise ValueError('Clues must be +, |, or -.') 28 | 29 | if len(clue_to_id) == 0: 30 | raise ValueError('Please provide at least one clue.') 31 | 32 | rs = utils.RectangularGridRegionSolver(E.R, E.C, max_num_regions = len(clue_to_id)) 33 | 34 | # Assign each clue to a Box 35 | clue_to_box = {} 36 | for (r, c) in clue_to_id: 37 | value = E.clues[(r, c)] 38 | box = Box(IntVar(0, E.R-1), IntVar(0, E.R-1), IntVar(0, E.C-1), IntVar(0, E.C-1)) 39 | clue_to_box[(r, c)] = box 40 | # Box preconditions. 41 | require(box.top <= box.bottom) 42 | require(box.left <= box.right) 43 | # Shape constraints. 44 | height = box.bottom - box.top 45 | width = box.right - box.left 46 | if value == '+': 47 | require(height == width) 48 | elif value == '|': 49 | require(width < height) 50 | elif value == '-': 51 | require(height < width) 52 | 53 | # Assign region IDs based on clue locations and Box corners 54 | for r in range(E.R): 55 | for c in range(E.C): 56 | for (y, x) in clue_to_id: 57 | box = clue_to_box[(y, x)] 58 | require(rs.region_id[y][x] == clue_to_id[(y, x)]) 59 | require(((box.top <= r) & (r <= box.bottom) & (box.left <= c) & (c <= box.right)) == \ 60 | (rs.region_id[r][c] == clue_to_id[(y, x)])) 61 | 62 | # No 4 boxes at same corner. 63 | for r in range(E.R-1): 64 | for c in range(E.C-1): 65 | four_cells = [rs.grid[y][x] \ 66 | for (y,x) in ((r,c), (r,c+1), (r+1,c), (r+1,c+1))] 67 | all_diff = BoolVar(True) 68 | for i in range(4): 69 | for j in range(i): 70 | all_diff &= four_cells[i] != four_cells[j] 71 | require(~all_diff) 72 | 73 | return rs.solutions() 74 | 75 | 76 | def decode(solutions): 77 | return utils.decode(solutions) 78 | -------------------------------------------------------------------------------- /solvers/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .borders import * 2 | from .encoding import * 3 | from .grids import * 4 | from .loops import * 5 | from .numbers import * 6 | from .regions import * 7 | from .shading import * 8 | from .shapes import * 9 | -------------------------------------------------------------------------------- /solvers/utils/numbers.py: -------------------------------------------------------------------------------- 1 | from ..claspy import * 2 | from .grids import * 3 | from .solutions import * 4 | from .encoding import * 5 | 6 | def factor_pairs(n): 7 | ''' 8 | n -> [all pairs (a,b) such that a*b=n] 9 | ''' 10 | pairs = [] 11 | for i in range(1, n+1): 12 | if n % i == 0: 13 | pairs.append((i, n//i)) 14 | return pairs 15 | 16 | class RectangularGridNumbersSolver: 17 | ''' 18 | Solves puzzles which require writing a number in each cell. 19 | ''' 20 | def __init__(self, rows, cols, min_value, max_value): 21 | ''' 22 | rows = # rows 23 | cols = # columns 24 | min_value = the minimum permissible integer value 25 | max_value = the maximum permissible integer value 26 | ''' 27 | self.__rows = rows 28 | self.__cols = cols 29 | self.__grid = RectangularGrid(rows, cols, lambda : IntVar(min_value, max_value)) 30 | @property 31 | def rows(self): 32 | return self.__rows 33 | @property 34 | def cols(self): 35 | return self.__cols 36 | @property 37 | def grid(self): 38 | return self.__grid 39 | def regions(self, regions): 40 | ''' 41 | Given a collection of regions, where each region consists of 42 | (r, c) coordinates, 43 | 44 | Require that the cells in that region are all distinct. 45 | ''' 46 | for region in regions: 47 | cells_in_region = [self.grid[r][c] for (r, c) in region] 48 | require_all_diff(cells_in_region) 49 | def rows_and_cols(self): 50 | ''' 51 | Require that the cells in every row are distinct, 52 | and that the cells in every column are distinct. 53 | ''' 54 | for r in range(self.rows): 55 | require_all_diff([self.grid[r][c] for c in range(self.cols)]) 56 | for c in range(self.cols): 57 | require_all_diff([self.grid[r][c] for r in range(self.rows)]) 58 | def solutions(self): 59 | ''' 60 | Get a list of solutions, where each solution is a list of cell 61 | values (which are numbers), read in a left-to-right, top-to-bottom 62 | ordering. 63 | ''' 64 | return get_all_grid_solutions(self.grid) 65 | -------------------------------------------------------------------------------- /solvers/utils/solutions.py: -------------------------------------------------------------------------------- 1 | from ..claspy import * 2 | from datetime import datetime 3 | 4 | MAX_SOLUTIONS_TO_FIND = 10 5 | 6 | def rc_to_grid(r, c): 7 | return f'{2*r+1},{2*c+1}' 8 | 9 | def default_equality_function(x, y): 10 | return x == y 11 | 12 | def get_all_solutions(generate_solution, avoid_duplicate_solution, debug_function = None): 13 | solutions = [] 14 | #print(f'starting search - it\'s {datetime.now()}', flush=True) 15 | for i in range(MAX_SOLUTIONS_TO_FIND): 16 | if claspy_solve(): 17 | # print(f'solution {i+1} found at {datetime.now()}', flush=True) 18 | solutions.append(generate_solution()) 19 | avoid_duplicate_solution() 20 | if debug_function: 21 | debug_function() 22 | else: 23 | break 24 | #print(f'all solutions found - it\'s {datetime.now()}', flush=True) 25 | return solutions 26 | 27 | def get_grid_solution(grid, format_function = None): 28 | 29 | if not format_function: 30 | format_function = lambda r, c: grid[r][c].value() 31 | 32 | solution = {} 33 | for r in range(len(grid)): 34 | for c in range(len(grid[r])): 35 | cell_output = format_function(r, c) 36 | if cell_output != '': 37 | solution[rc_to_grid(r,c)] = cell_output 38 | return solution 39 | 40 | def avoid_duplicate_grid_solution(grid, equality_function = default_equality_function): 41 | x = BoolVar(True) 42 | for r in range(len(grid)): 43 | for c in range(len(grid[r])): 44 | x = x & equality_function(grid[r][c], grid[r][c].value()) 45 | require(~x) 46 | 47 | def get_all_grid_solutions(grid, 48 | equality_function = default_equality_function, 49 | format_function = None, 50 | debug_function = None): 51 | 52 | def generate_solution(): 53 | return get_grid_solution(grid, format_function) 54 | 55 | def avoid_duplicate_solution(): 56 | return avoid_duplicate_grid_solution(grid, equality_function) 57 | 58 | return get_all_solutions(generate_solution, avoid_duplicate_solution, debug_function) 59 | 60 | -------------------------------------------------------------------------------- /solvers/yajilin.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | 4 | def encode(string): 5 | return utils.encode(string, clue_encoder = lambda s : s) 6 | 7 | def solve(E): 8 | # Restrict the number of bits used for IntVar. 9 | # The highest number that we need is the highest clue number. 10 | set_max_val(max([int(clue[0][0]) for clue in E.clues.values() if clue != 'gray'], default=1)) 11 | 12 | loop_solver = utils.RectangularGridLoopSolver(E.R, E.C, shading = True) 13 | shading_solver = utils.RectangularGridShadingSolver( 14 | E.R, E.C, grid = loop_solver.grid, shading_symbols = ['.']) 15 | loop_solver.loop(E.clues, allow_blanks = False) 16 | shading_solver.no_adjacent() 17 | 18 | # ----CLUE RULES---- 19 | 20 | for r in range(E.R): 21 | for c in range(E.C): 22 | # clues satisfied 23 | if (r, c) in E.clues: 24 | if E.clues[(r,c)] == 'gray': 25 | require(loop_solver.grid[r][c] == '') 26 | else: 27 | num_string = E.clues[(r,c)][0][0] 28 | direction = E.clues[(r,c)][0][1] 29 | # check the clue for validity 30 | if not num_string.isnumeric() or direction not in 'lrud': 31 | raise ValueError('Please ensure that each clue has both a number and a direction.') 32 | 33 | # build a list of coordinates that are "seen" by this clue 34 | seen_cells = [] 35 | if direction == 'l': 36 | seen_cells = [(r,x) for x in range(0, c)] 37 | elif direction == 'r': 38 | seen_cells = [(r,x) for x in range(c+1, E.C)] 39 | elif direction == 'u': 40 | seen_cells = [(y,c) for y in range(0, r)] 41 | elif direction == 'd': 42 | seen_cells = [(y,c) for y in range(r+1, E.R)] 43 | # get a list of boolean variables that tell you whether the cells are shaded 44 | shaded_seen = [BoolVar(loop_solver.grid[y][x] == '.') for (y,x) in seen_cells] 45 | # require that exactly 'num' of the cells are shaded 46 | require(sum_bools(int(num_string), shaded_seen)) 47 | 48 | return loop_solver.solutions() 49 | 50 | def decode(solutions): 51 | return utils.decode(solutions) 52 | -------------------------------------------------------------------------------- /solvers/yinyang.py: -------------------------------------------------------------------------------- 1 | from .claspy import * 2 | from . import utils 3 | from .utils.solutions import * 4 | 5 | def encode(string): 6 | return utils.encode(string, clue_encoder = lambda s: s) 7 | 8 | def solve(E): 9 | set_max_val(2) 10 | 11 | s = utils.shading.RectangularGridShadingSolver(E.R, E.C) 12 | 13 | # Optimize solving by providing known roots for white and black parts 14 | white_root, black_root = None, None 15 | for (r, c) in E.clues: 16 | if E.clues[(r,c)] == 'w': 17 | white_root = (r,c) 18 | else: 19 | black_root = (r,c) 20 | if white_root and black_root: 21 | break 22 | 23 | s.white_connectivity(white_root) 24 | s.black_connectivity(black_root) 25 | s.no_white_2x2() 26 | s.no_black_2x2() 27 | 28 | for (r, c) in E.clues: 29 | require(s.grid[r][c] == (E.clues[(r,c)] == 'b')) 30 | 31 | def format_function(r, c): 32 | return ('black' if s.grid[r][c].value() else 'white') + '_circle.png' 33 | 34 | return get_all_grid_solutions(s.grid, format_function = format_function) 35 | 36 | def decode(solutions): 37 | return utils.decode(solutions) 38 | -------------------------------------------------------------------------------- /static/admin/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* DASHBOARD */ 2 | 3 | .dashboard .module table th { 4 | width: 100%; 5 | } 6 | 7 | .dashboard .module table td { 8 | white-space: nowrap; 9 | } 10 | 11 | .dashboard .module table td a { 12 | display: block; 13 | padding-right: .6em; 14 | } 15 | 16 | /* RECENT ACTIONS MODULE */ 17 | 18 | .module ul.actionlist { 19 | margin-left: 0; 20 | } 21 | 22 | ul.actionlist li { 23 | list-style-type: none; 24 | overflow: hidden; 25 | text-overflow: ellipsis; 26 | -o-text-overflow: ellipsis; 27 | } 28 | -------------------------------------------------------------------------------- /static/admin/css/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Roboto'; 3 | src: url('../fonts/Roboto-Bold-webfont.woff'); 4 | font-weight: 700; 5 | font-style: normal; 6 | } 7 | 8 | @font-face { 9 | font-family: 'Roboto'; 10 | src: url('../fonts/Roboto-Regular-webfont.woff'); 11 | font-weight: 400; 12 | font-style: normal; 13 | } 14 | 15 | @font-face { 16 | font-family: 'Roboto'; 17 | src: url('../fonts/Roboto-Light-webfont.woff'); 18 | font-weight: 300; 19 | font-style: normal; 20 | } 21 | -------------------------------------------------------------------------------- /static/admin/css/login.css: -------------------------------------------------------------------------------- 1 | /* LOGIN FORM */ 2 | 3 | body.login { 4 | background: #f8f8f8; 5 | } 6 | 7 | .login #header { 8 | height: auto; 9 | padding: 15px 16px; 10 | justify-content: center; 11 | } 12 | 13 | .login #header h1 { 14 | font-size: 18px; 15 | } 16 | 17 | .login #header h1 a { 18 | color: #fff; 19 | } 20 | 21 | .login #content { 22 | padding: 20px 20px 0; 23 | } 24 | 25 | .login #container { 26 | background: #fff; 27 | border: 1px solid #eaeaea; 28 | border-radius: 4px; 29 | overflow: hidden; 30 | width: 28em; 31 | min-width: 300px; 32 | margin: 100px auto; 33 | } 34 | 35 | .login #content-main { 36 | width: 100%; 37 | } 38 | 39 | .login .form-row { 40 | padding: 4px 0; 41 | float: left; 42 | width: 100%; 43 | border-bottom: none; 44 | } 45 | 46 | .login .form-row label { 47 | padding-right: 0.5em; 48 | line-height: 2em; 49 | font-size: 1em; 50 | clear: both; 51 | color: #333; 52 | } 53 | 54 | .login .form-row #id_username, .login .form-row #id_password { 55 | clear: both; 56 | padding: 8px; 57 | width: 100%; 58 | -webkit-box-sizing: border-box; 59 | -moz-box-sizing: border-box; 60 | box-sizing: border-box; 61 | } 62 | 63 | .login span.help { 64 | font-size: 10px; 65 | display: block; 66 | } 67 | 68 | .login .submit-row { 69 | clear: both; 70 | padding: 1em 0 0 9.4em; 71 | margin: 0; 72 | border: none; 73 | background: none; 74 | text-align: left; 75 | } 76 | 77 | .login .password-reset-link { 78 | text-align: center; 79 | } 80 | -------------------------------------------------------------------------------- /static/admin/css/nav_sidebar.css: -------------------------------------------------------------------------------- 1 | .sticky { 2 | position: sticky; 3 | top: 0; 4 | max-height: 100vh; 5 | } 6 | 7 | .toggle-nav-sidebar { 8 | z-index: 20; 9 | left: 0; 10 | display: flex; 11 | align-items: center; 12 | justify-content: center; 13 | flex: 0 0 23px; 14 | width: 23px; 15 | border: 0; 16 | border-right: 1px solid var(--hairline-color); 17 | background-color: var(--body-bg); 18 | cursor: pointer; 19 | font-size: 20px; 20 | color: var(--link-fg); 21 | padding: 0; 22 | } 23 | 24 | [dir="rtl"] .toggle-nav-sidebar { 25 | border-left: 1px solid var(--hairline-color); 26 | border-right: 0; 27 | } 28 | 29 | .toggle-nav-sidebar:hover, 30 | .toggle-nav-sidebar:focus { 31 | background-color: var(--darkened-bg); 32 | } 33 | 34 | #nav-sidebar { 35 | z-index: 15; 36 | flex: 0 0 275px; 37 | left: -276px; 38 | margin-left: -276px; 39 | border-top: 1px solid transparent; 40 | border-right: 1px solid var(--hairline-color); 41 | background-color: var(--body-bg); 42 | overflow: auto; 43 | } 44 | 45 | [dir="rtl"] #nav-sidebar { 46 | border-left: 1px solid var(--hairline-color); 47 | border-right: 0; 48 | left: 0; 49 | margin-left: 0; 50 | right: -276px; 51 | margin-right: -276px; 52 | } 53 | 54 | .toggle-nav-sidebar::before { 55 | content: '\00BB'; 56 | } 57 | 58 | .main.shifted .toggle-nav-sidebar::before { 59 | content: '\00AB'; 60 | } 61 | 62 | .main.shifted > #nav-sidebar { 63 | left: 24px; 64 | margin-left: 0; 65 | } 66 | 67 | [dir="rtl"] .main.shifted > #nav-sidebar { 68 | left: 0; 69 | right: 24px; 70 | margin-right: 0; 71 | } 72 | 73 | #nav-sidebar .module th { 74 | width: 100%; 75 | overflow-wrap: anywhere; 76 | } 77 | 78 | #nav-sidebar .module th, 79 | #nav-sidebar .module caption { 80 | padding-left: 16px; 81 | } 82 | 83 | #nav-sidebar .module td { 84 | white-space: nowrap; 85 | } 86 | 87 | [dir="rtl"] #nav-sidebar .module th, 88 | [dir="rtl"] #nav-sidebar .module caption { 89 | padding-left: 8px; 90 | padding-right: 16px; 91 | } 92 | 93 | #nav-sidebar .current-app .section:link, 94 | #nav-sidebar .current-app .section:visited { 95 | color: var(--header-color); 96 | font-weight: bold; 97 | } 98 | 99 | #nav-sidebar .current-model { 100 | background: var(--selected-row); 101 | } 102 | 103 | .main > #nav-sidebar + .content { 104 | max-width: calc(100% - 23px); 105 | } 106 | 107 | .main.shifted > #nav-sidebar + .content { 108 | max-width: calc(100% - 299px); 109 | } 110 | 111 | @media (max-width: 767px) { 112 | #nav-sidebar, #toggle-nav-sidebar { 113 | display: none; 114 | } 115 | 116 | .main > #nav-sidebar + .content, 117 | .main.shifted > #nav-sidebar + .content { 118 | max-width: 100%; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /static/admin/css/responsive_rtl.css: -------------------------------------------------------------------------------- 1 | /* TABLETS */ 2 | 3 | @media (max-width: 1024px) { 4 | [dir="rtl"] .colMS { 5 | margin-right: 0; 6 | } 7 | 8 | [dir="rtl"] #user-tools { 9 | text-align: right; 10 | } 11 | 12 | [dir="rtl"] #changelist .actions label { 13 | padding-left: 10px; 14 | padding-right: 0; 15 | } 16 | 17 | [dir="rtl"] #changelist .actions select { 18 | margin-left: 0; 19 | margin-right: 15px; 20 | } 21 | 22 | [dir="rtl"] .change-list .filtered .results, 23 | [dir="rtl"] .change-list .filtered .paginator, 24 | [dir="rtl"] .filtered #toolbar, 25 | [dir="rtl"] .filtered div.xfull, 26 | [dir="rtl"] .filtered .actions { 27 | margin-right: 0; 28 | margin-left: 230px; 29 | } 30 | 31 | [dir="rtl"] .inline-group ul.tools a.add, 32 | [dir="rtl"] .inline-group div.add-row a, 33 | [dir="rtl"] .inline-group .tabular tr.add-row td a { 34 | padding: 8px 26px 8px 10px; 35 | background-position: calc(100% - 8px) 9px; 36 | } 37 | 38 | [dir="rtl"] .related-widget-wrapper-link + .selector { 39 | margin-right: 0; 40 | margin-left: 15px; 41 | } 42 | 43 | [dir="rtl"] .selector .selector-filter label { 44 | margin-right: 0; 45 | margin-left: 8px; 46 | } 47 | 48 | [dir="rtl"] .object-tools li { 49 | float: right; 50 | } 51 | 52 | [dir="rtl"] .object-tools li + li { 53 | margin-left: 0; 54 | margin-right: 15px; 55 | } 56 | 57 | [dir="rtl"] .dashboard .module table td a { 58 | padding-left: 0; 59 | padding-right: 16px; 60 | } 61 | } 62 | 63 | /* MOBILE */ 64 | 65 | @media (max-width: 767px) { 66 | [dir="rtl"] .change-list .filtered .results, 67 | [dir="rtl"] .change-list .filtered .paginator, 68 | [dir="rtl"] .filtered #toolbar, 69 | [dir="rtl"] .filtered div.xfull, 70 | [dir="rtl"] .filtered .actions { 71 | margin-left: 0; 72 | } 73 | 74 | [dir="rtl"] .aligned .add-another, 75 | [dir="rtl"] .aligned .related-lookup, 76 | [dir="rtl"] .aligned .datetimeshortcuts { 77 | margin-left: 0; 78 | margin-right: 15px; 79 | } 80 | 81 | [dir="rtl"] .aligned ul { 82 | margin-right: 0; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /static/admin/css/vendor/select2/LICENSE-SELECT2.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2015 Kevin Brown, Igor Vaynberg, and Select2 contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /static/admin/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Roboto webfont source: https://www.google.com/fonts/specimen/Roboto 2 | WOFF files extracted using https://github.com/majodev/google-webfonts-helper 3 | Weights used in this project: Light (300), Regular (400), Bold (700) 4 | -------------------------------------------------------------------------------- /static/admin/fonts/Roboto-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/admin/fonts/Roboto-Bold-webfont.woff -------------------------------------------------------------------------------- /static/admin/fonts/Roboto-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/admin/fonts/Roboto-Light-webfont.woff -------------------------------------------------------------------------------- /static/admin/fonts/Roboto-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/admin/fonts/Roboto-Regular-webfont.woff -------------------------------------------------------------------------------- /static/admin/img/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Code Charm Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /static/admin/img/README.txt: -------------------------------------------------------------------------------- 1 | All icons are taken from Font Awesome (http://fontawesome.io/) project. 2 | The Font Awesome font is licensed under the SIL OFL 1.1: 3 | - https://scripts.sil.org/OFL 4 | 5 | SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG 6 | Font-Awesome-SVG-PNG is licensed under the MIT license (see file license 7 | in current folder). 8 | -------------------------------------------------------------------------------- /static/admin/img/calendar-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /static/admin/img/gis/move_vertex_off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/admin/img/gis/move_vertex_on.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/admin/img/icon-addlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-alert.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-calendar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /static/admin/img/icon-changelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /static/admin/img/icon-deletelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-no.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-unknown-alt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-viewlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/inline-delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/sorting-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /static/admin/img/tooltag-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/tooltag-arrowright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/js/actions.min.js: -------------------------------------------------------------------------------- 1 | (function(a){var f;a.fn.actions=function(e){var b=a.extend({},a.fn.actions.defaults,e),g=a(this),k=!1,l=function(){a(b.acrossClears).hide();a(b.acrossQuestions).show();a(b.allContainer).hide()},m=function(){a(b.acrossClears).show();a(b.acrossQuestions).hide();a(b.actionContainer).toggleClass(b.selectedClass);a(b.allContainer).show();a(b.counterContainer).hide()},n=function(){a(b.acrossClears).hide();a(b.acrossQuestions).hide();a(b.allContainer).hide();a(b.counterContainer).show()},p=function(){n(); 2 | a(b.acrossInput).val(0);a(b.actionContainer).removeClass(b.selectedClass)},q=function(c){c?l():n();a(g).prop("checked",c).parent().parent().toggleClass(b.selectedClass,c)},h=function(){var c=a(g).filter(":checked").length,d=a(".action-counter").data("actionsIcnt");a(b.counterContainer).html(interpolate(ngettext("%(sel)s of %(cnt)s selected","%(sel)s of %(cnt)s selected",c),{sel:c,cnt:d},!0));a(b.allToggle).prop("checked",function(){if(c===g.length){var a=!0;l()}else a=!1,p();return a})};a(b.counterContainer).show(); 3 | a(this).filter(":checked").each(function(c){a(this).parent().parent().toggleClass(b.selectedClass);h();1===a(b.acrossInput).val()&&m()});a(b.allToggle).show().on("click",function(){q(a(this).prop("checked"));h()});a("a",b.acrossQuestions).on("click",function(c){c.preventDefault();a(b.acrossInput).val(1);m()});a("a",b.acrossClears).on("click",function(c){c.preventDefault();a(b.allToggle).prop("checked",!1);p();q(0);h()});f=null;a(g).on("click",function(c){c||(c=window.event);var d=c.target?c.target: 4 | c.srcElement;if(f&&a.data(f)!==a.data(d)&&!0===c.shiftKey){var e=!1;a(f).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked);a(g).each(function(){if(a.data(this)===a.data(f)||a.data(this)===a.data(d))e=e?!1:!0;e&&a(this).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked)})}a(d).parent().parent().toggleClass(b.selectedClass,d.checked);f=d;h()});a("form#changelist-form table#result_list tr").on("change","td:gt(0) :input",function(){k=!0}); 5 | a('form#changelist-form button[name="index"]').on("click",function(a){if(k)return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."))});a('form#changelist-form input[name="_save"]').on("click",function(c){var d=!1;a("select option:selected",b.actionContainer).each(function(){a(this).val()&&(d=!0)});if(d)return k?confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")): 6 | confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button."))})};a.fn.actions.defaults={actionContainer:"div.actions",counterContainer:"span.action-counter",allContainer:"div.actions span.all",acrossInput:"div.actions input.select-across",acrossQuestions:"div.actions span.question",acrossClears:"div.actions span.clear",allToggle:"#action-toggle",selectedClass:"selected"};a(document).ready(function(){var e= 7 | a("tr input.action-select");0 0) { 26 | values.push(field.val()); 27 | } 28 | }); 29 | prepopulatedField.val(URLify(values.join(' '), maxLength, allowUnicode)); 30 | }; 31 | 32 | prepopulatedField.data('_changed', false); 33 | prepopulatedField.on('change', function() { 34 | prepopulatedField.data('_changed', true); 35 | }); 36 | 37 | if (!prepopulatedField.val()) { 38 | $(dependencies.join(',')).on('keyup change focus', populate); 39 | } 40 | }); 41 | }; 42 | })(django.jQuery); 43 | -------------------------------------------------------------------------------- /static/admin/js/prepopulate.min.js: -------------------------------------------------------------------------------- 1 | (function(b){b.fn.prepopulate=function(d,f,g){return this.each(function(){var a=b(this),h=function(){if(!a.data("_changed")){var e=[];b.each(d,function(a,c){c=b(c);01&&(n+="a"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Моля въведете още "+t+" символ";return t>1&&(n+="a"),n},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(e){var t="Можете да направите до "+e.maximum+" ";return e.maximum>1?t+="избора":t+="избор",t},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/bn.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bn",[],function(){return{errorLoading:function(){return"ফলাফলগুলি লোড করা যায়নি।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।";return 1!=e&&(u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।"),u},inputTooShort:function(n){return n.minimum-n.input.length+" টি অক্ষর অথবা অধিক অক্ষর লিখুন।"},loadingMore:function(){return"আরো ফলাফল লোড হচ্ছে ..."},maximumSelected:function(n){var e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।";return 1!=n.maximum&&(e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।"),e},noResults:function(){return"কোন ফলাফল পাওয়া যায়নি।"},searching:function(){return"অনুসন্ধান করা হচ্ছে ..."}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/bs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/bs",[],function(){function e(e,n,r,t){return e%10==1&&e%100!=11?n:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspijelo."},inputTooLong:function(n){var r=n.input.length-n.maximum,t="Obrišite "+r+" simbol";return t+=e(r,"","a","a")},inputTooShort:function(n){var r=n.minimum-n.input.length,t="Ukucajte bar još "+r+" simbol";return t+=e(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(n){var r="Možete izabrati samo "+n.maximum+" stavk";return r+=e(n.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Uklonite sve stavke"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/ca.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Si us plau, elimina "+t+" car";return t==1?n+="àcter":n+="àcters",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Si us plau, introdueix "+t+" car";return t==1?n+="àcter":n+="àcters",n},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var t="Només es pot seleccionar "+e.maximum+" element";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/cs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/cs",[],function(){function e(e,t){switch(e){case 2:return t?"dva":"dvě";case 3:return"tři";case 4:return"čtyři"}return""}return{errorLoading:function(){return"Výsledky nemohly být načteny."},inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?"Prosím zadejte o jeden znak méně":n<=4?"Prosím zadejte o "+e(n,!0)+" znaky méně":"Prosím zadejte o "+n+" znaků méně"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?"Prosím zadejte ještě jeden znak":n<=4?"Prosím zadejte ještě další "+e(n,!0)+" znaky":"Prosím zadejte ještě dalších "+n+" znaků"},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(t){var n=t.maximum;return n==1?"Můžete zvolit jen jednu položku":n<=4?"Můžete zvolit maximálně "+e(n,!1)+" položky":"Můžete zvolit maximálně "+n+" položek"},noResults:function(){return"Nenalezeny žádné položky"},searching:function(){return"Vyhledávání…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/da.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Angiv venligst "+t+" tegn mindre";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Angiv venligst "+t+" tegn mere";return n},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var t="Du kan kun vælge "+e.maximum+" emne";return e.maximum!=1&&(t+="r"),t},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/de.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/de",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return"Bitte "+t+" Zeichen weniger eingeben"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Bitte "+t+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var t="Sie können nur "+e.maximum+" Eintr";return e.maximum===1?t+="ag":t+="äge",t+=" auswählen",t},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/dsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/dsb",[],function(){var n=["znamuško","znamušce","znamuška","znamuškow"],e=["zapisk","zapiska","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njejsu se dali zacytaś."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Pšosym lašuj "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Pšosym zapódaj nanejmjenjej "+a+" "+u(a,n)},loadingMore:function(){return"Dalšne wuslědki se zacytaju…"},maximumSelected:function(n){return"Móžoš jano "+n.maximum+" "+u(n.maximum,e)+"wubraś."},noResults:function(){return"Žedne wuslědki namakane"},searching:function(){return"Pyta se…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/el.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Παρακαλώ διαγράψτε "+t+" χαρακτήρ";return t==1&&(n+="α"),t!=1&&(n+="ες"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Παρακαλώ συμπληρώστε "+t+" ή περισσότερους χαρακτήρες";return n},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(e){var t="Μπορείτε να επιλέξετε μόνο "+e.maximum+" επιλογ";return e.maximum==1&&(t+="ή"),e.maximum!=1&&(t+="ές"),t},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/en.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Please delete "+t+" character";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Please enter "+t+" or more characters";return n},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var t="You can only select "+e.maximum+" item";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No results found"},searching:function(){return"Searching…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/es.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"La carga falló"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Por favor, elimine "+t+" car";return t==1?n+="ácter":n+="acteres",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Por favor, introduzca "+t+" car";return t==1?n+="ácter":n+="acteres",n},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var t="Sólo puede seleccionar "+e.maximum+" elemento";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/et.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Sisesta "+t+" täht";return t!=1&&(n+="e"),n+=" vähem",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Sisesta "+t+" täht";return t!=1&&(n+="e"),n+=" rohkem",n},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var t="Saad vaid "+e.maximum+" tulemus";return e.maximum==1?t+="e":t+="t",t+=" valida",t},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/eu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return t==1?n+="karaktere bat":n+=t+" karaktere",n+=" gutxiago",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return t==1?n+="karaktere bat":n+=t+" karaktere",n+=" gehiago",n},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return e.maximum===1?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/fa.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="لطفاً "+t+" کاراکتر را حذف نمایید";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="لطفاً تعداد "+t+" کاراکتر یا بیشتر وارد نمایید";return n},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(e){var t="شما تنها می‌توانید "+e.maximum+" آیتم را انتخاب نمایید";return t},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/fi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fi",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return"Ole hyvä ja anna "+t+" merkkiä vähemmän"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Ole hyvä ja anna "+t+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(e){return"Voit valita ainoastaan "+e.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/fr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Supprimez "+t+" caractère";return t!==1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Saisissez "+t+" caractère";return t!==1&&(n+="s"),n},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){var t="Vous pouvez seulement sélectionner "+e.maximum+" élément";return e.maximum!==1&&(t+="s"),t},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/gl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/gl",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Elimine ";return t===1?n+="un carácter":n+=t+" caracteres",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Engada ";return t===1?n+="un carácter":n+=t+" caracteres",n},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){var t="Só pode ";return e.maximum===1?t+="un elemento":t+=e.maximum+" elementos",t},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/he.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="נא למחוק ";return t===1?n+="תו אחד":n+=t+" תווים",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="נא להכניס ";return t===1?n+="תו אחד":n+=t+" תווים",n+=" או יותר",n},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(e){var t="באפשרותך לבחור עד ";return e.maximum===1?t+="פריט אחד":t+=e.maximum+" פריטים",t},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/hi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" अक्षर को हटा दें";return t>1&&(n=t+" अक्षरों को हटा दें "),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="कृपया "+t+" या अधिक अक्षर दर्ज करें";return n},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(e){var t="आप केवल "+e.maximum+" आइटम का चयन कर सकते हैं";return t},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/hr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hr",[],function(){function e(e){var t=" "+e+" znak";return e%10<5&&e%10>0&&(e%100<5||e%100>19)?e%10>1&&(t+="a"):t+="ova",t}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(t){var n=t.input.length-t.maximum;return"Unesite "+e(n)},inputTooShort:function(t){var n=t.minimum-t.input.length;return"Unesite još "+e(n)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(e){return"Maksimalan broj odabranih stavki je "+e.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/hsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hsb",[],function(){var n=["znamješko","znamješce","znamješka","znamješkow"],e=["zapisk","zapiskaj","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njedachu so začitać."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Prošu zhašej "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Prošu zapodaj znajmjeńša "+a+" "+u(a,n)},loadingMore:function(){return"Dalše wuslědki so začitaja…"},maximumSelected:function(n){return"Móžeš jenož "+n.maximum+" "+u(n.maximum,e)+"wubrać"},noResults:function(){return"Žane wuslědki namakane"},searching:function(){return"Pyta so…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/hu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return"Túl hosszú. "+t+" karakterrel több, mint kellene."},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Túl rövid. Még "+t+" karakter hiányzik."},loadingMore:function(){return"Töltés…"},maximumSelected:function(e){return"Csak "+e.maximum+" elemet lehet kiválasztani."},noResults:function(){return"Nincs találat."},searching:function(){return"Keresés…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/hy.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hy",[],function(){return{errorLoading:function(){return"Արդյունքները հնարավոր չէ բեռնել։"},inputTooLong:function(n){return"Խնդրում ենք հեռացնել "+(n.input.length-n.maximum)+" նշան"},inputTooShort:function(n){return"Խնդրում ենք մուտքագրել "+(n.minimum-n.input.length)+" կամ ավել նշաններ"},loadingMore:function(){return"Բեռնվում են նոր արդյունքներ․․․"},maximumSelected:function(n){return"Դուք կարող եք ընտրել առավելագույնը "+n.maximum+" կետ"},noResults:function(){return"Արդյունքներ չեն գտնվել"},searching:function(){return"Որոնում․․․"},removeAllItems:function(){return"Հեռացնել բոլոր տարրերը"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/id.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Hapuskan "+t+" huruf"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Masukkan "+t+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(e){return"Anda hanya dapat memilih "+e.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/is.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/is",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vinsamlegast styttið texta um "+t+" staf";return t<=1?n:n+"i"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vinsamlegast skrifið "+t+" staf";return t>1&&(n+="i"),n+=" í viðbót",n},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(e){return"Þú getur aðeins valið "+e.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/it.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Per favore cancella "+t+" caratter";return t!==1?n+="i":n+="e",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Per favore inserisci "+t+" o più caratteri";return n},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var t="Puoi selezionare solo "+e.maximum+" element";return e.maximum!==1?t+="i":t+="o",t},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/ja.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" 文字を削除してください";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="少なくとも "+t+" 文字を入力してください";return n},loadingMore:function(){return"読み込み中…"},maximumSelected:function(e){var t=e.maximum+" 件しか選択できません";return t},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/ka.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ka",[],function(){return{errorLoading:function(){return"მონაცემების ჩატვირთვა შეუძლებელია."},inputTooLong:function(n){return"გთხოვთ აკრიფეთ "+(n.input.length-n.maximum)+" სიმბოლოთი ნაკლები"},inputTooShort:function(n){return"გთხოვთ აკრიფეთ "+(n.minimum-n.input.length)+" სიმბოლო ან მეტი"},loadingMore:function(){return"მონაცემების ჩატვირთვა…"},maximumSelected:function(n){return"თქვენ შეგიძლიათ აირჩიოთ არაუმეტეს "+n.maximum+" ელემენტი"},noResults:function(){return"რეზულტატი არ მოიძებნა"},searching:function(){return"ძიება…"},removeAllItems:function(){return"ამოიღე ყველა ელემენტი"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/km.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/km",[],function(){return{errorLoading:function(){return"មិនអាចទាញយកទិន្នន័យ"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="សូមលុបចេញ "+t+" អក្សរ";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="សូមបញ្ចូល"+t+" អក្សរ រឺ ច្រើនជាងនេះ";return n},loadingMore:function(){return"កំពុងទាញយកទិន្នន័យបន្ថែម..."},maximumSelected:function(e){var t="អ្នកអាចជ្រើសរើសបានតែ "+e.maximum+" ជម្រើសប៉ុណ្ណោះ";return t},noResults:function(){return"មិនមានលទ្ធផល"},searching:function(){return"កំពុងស្វែងរក..."}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/ko.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="너무 깁니다. "+t+" 글자 지워주세요.";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="너무 짧습니다. "+t+" 글자 더 입력해주세요.";return n},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(e){var t="최대 "+e.maximum+"개까지만 선택 가능합니다.";return t},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/lt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/lt",[],function(){function e(e,t,n,r){return e%10===1&&(e%100<11||e%100>19)?t:e%10>=2&&e%10<=9&&(e%100<11||e%100>19)?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r="Pašalinkite "+n+" simbol";return r+=e(n,"į","ius","ių"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Įrašykite dar "+n+" simbol";return r+=e(n,"į","ius","ių"),r},loadingMore:function(){return"Kraunama daugiau rezultatų…"},maximumSelected:function(t){var n="Jūs galite pasirinkti tik "+t.maximum+" element";return n+=e(t.maximum,"ą","us","ų"),n},noResults:function(){return"Atitikmenų nerasta"},searching:function(){return"Ieškoma…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/lv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/lv",[],function(){function e(e,t,n,r){return e===11?t:e%10===1?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r="Lūdzu ievadiet par "+n;return r+=" simbol"+e(n,"iem","u","iem"),r+" mazāk"},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Lūdzu ievadiet vēl "+n;return r+=" simbol"+e(n,"us","u","us"),r},loadingMore:function(){return"Datu ielāde…"},maximumSelected:function(t){var n="Jūs varat izvēlēties ne vairāk kā "+t.maximum;return n+=" element"+e(t.maximum,"us","u","us"),n},noResults:function(){return"Sakritību nav"},searching:function(){return"Meklēšana…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/mk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/mk",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Ве молиме внесете "+e.maximum+" помалку карактер";return e.maximum!==1&&(n+="и"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Ве молиме внесете уште "+e.maximum+" карактер";return e.maximum!==1&&(n+="и"),n},loadingMore:function(){return"Вчитување резултати…"},maximumSelected:function(e){var t="Можете да изберете само "+e.maximum+" ставк";return e.maximum===1?t+="а":t+="и",t},noResults:function(){return"Нема пронајдено совпаѓања"},searching:function(){return"Пребарување…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/ms.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ms",[],function(){return{errorLoading:function(){return"Keputusan tidak berjaya dimuatkan."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Sila hapuskan "+t+" aksara"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Sila masukkan "+t+" atau lebih aksara"},loadingMore:function(){return"Sedang memuatkan keputusan…"},maximumSelected:function(e){return"Anda hanya boleh memilih "+e.maximum+" pilihan"},noResults:function(){return"Tiada padanan yang ditemui"},searching:function(){return"Mencari…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/nb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Vennligst fjern "+t+" tegn"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vennligst skriv inn ";return t>1?n+=" flere tegn":n+=" tegn til",n},loadingMore:function(){return"Laster flere resultater…"},maximumSelected:function(e){return"Du kan velge maks "+e.maximum+" elementer"},noResults:function(){return"Ingen treff"},searching:function(){return"Søker…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/ne.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ne",[],function(){return{errorLoading:function(){return"नतिजाहरु देखाउन सकिएन।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="कृपया "+e+" अक्षर मेटाउनुहोस्।";return 1!=e&&(u+="कृपया "+e+" अक्षरहरु मेटाउनुहोस्।"),u},inputTooShort:function(n){return"कृपया बाँकी रहेका "+(n.minimum-n.input.length)+" वा अरु धेरै अक्षरहरु भर्नुहोस्।"},loadingMore:function(){return"अरु नतिजाहरु भरिँदैछन् …"},maximumSelected:function(n){var e="तँपाई "+n.maximum+" वस्तु मात्र छान्न पाउँनुहुन्छ।";return 1!=n.maximum&&(e="तँपाई "+n.maximum+" वस्तुहरु मात्र छान्न पाउँनुहुन्छ।"),e},noResults:function(){return"कुनै पनि नतिजा भेटिएन।"},searching:function(){return"खोजि हुँदैछ…"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/nl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/nl",[],function(){return{errorLoading:function(){return"De resultaten konden niet worden geladen."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Gelieve "+t+" karakters te verwijderen";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Gelieve "+t+" of meer karakters in te voeren";return n},loadingMore:function(){return"Meer resultaten laden…"},maximumSelected:function(e){var t=e.maximum==1?"kan":"kunnen",n="Er "+t+" maar "+e.maximum+" item";return e.maximum!=1&&(n+="s"),n+=" worden geselecteerd",n},noResults:function(){return"Geen resultaten gevonden…"},searching:function(){return"Zoeken…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/pl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pl",[],function(){var e=["znak","znaki","znaków"],t=["element","elementy","elementów"],n=function(t,n){if(t===1)return n[0];if(t>1&&t<=4)return n[1];if(t>=5)return n[2]};return{errorLoading:function(){return"Nie można załadować wyników."},inputTooLong:function(t){var r=t.input.length-t.maximum;return"Usuń "+r+" "+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return"Podaj przynajmniej "+r+" "+n(r,e)},loadingMore:function(){return"Trwa ładowanie…"},maximumSelected:function(e){return"Możesz zaznaczyć tylko "+e.maximum+" "+n(e.maximum,t)},noResults:function(){return"Brak wyników"},searching:function(){return"Trwa wyszukiwanie…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/ps.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ps",[],function(){return{errorLoading:function(){return"پايلي نه سي ترلاسه کېدای"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="د مهربانۍ لمخي "+e+" توری ړنګ کړئ";return 1!=e&&(r=r.replace("توری","توري")),r},inputTooShort:function(n){return"لږ تر لږه "+(n.minimum-n.input.length)+" يا ډېر توري وليکئ"},loadingMore:function(){return"نوري پايلي ترلاسه کيږي..."},maximumSelected:function(n){var e="تاسو يوازي "+n.maximum+" قلم په نښه کولای سی";return 1!=n.maximum&&(e=e.replace("قلم","قلمونه")),e},noResults:function(){return"پايلي و نه موندل سوې"},searching:function(){return"لټول کيږي..."},removeAllItems:function(){return"ټول توکي لرې کړئ"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/pt-BR.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pt-BR",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Apague "+t+" caracter";return t!=1&&(n+="es"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Digite "+t+" ou mais caracteres";return n},loadingMore:function(){return"Carregando mais resultados…"},maximumSelected:function(e){var t="Você só pode selecionar "+e.maximum+" ite";return e.maximum==1?t+="m":t+="ns",t},noResults:function(){return"Nenhum resultado encontrado"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/pt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Por favor apague "+t+" ";return n+=t!=1?"caracteres":"carácter",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Introduza "+t+" ou mais caracteres";return n},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var t="Apenas pode seleccionar "+e.maximum+" ";return t+=e.maximum!=1?"itens":"item",t},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/ro.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ro",[],function(){return{errorLoading:function(){return"Rezultatele nu au putut fi incărcate."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vă rugăm să ștergeți"+t+" caracter";return t!==1&&(n+="e"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vă rugăm să introduceți "+t+"sau mai multe caractere";return n},loadingMore:function(){return"Se încarcă mai multe rezultate…"},maximumSelected:function(e){var t="Aveți voie să selectați cel mult "+e.maximum;return t+=" element",e.maximum!==1&&(t+="e"),t},noResults:function(){return"Nu au fost găsite rezultate"},searching:function(){return"Căutare…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/ru.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ru",[],function(){function e(e,t,n,r){return e%10<5&&e%10>0&&e%100<5||e%100>20?e%10>1?n:t:r}return{errorLoading:function(){return"Невозможно загрузить результаты"},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Пожалуйста, введите на "+n+" символ";return r+=e(n,"","a","ов"),r+=" меньше",r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Пожалуйста, введите еще хотя бы "+n+" символ";return r+=e(n,"","a","ов"),r},loadingMore:function(){return"Загрузка данных…"},maximumSelected:function(t){var n="Вы можете выбрать не более "+t.maximum+" элемент";return n+=e(t.maximum,"","a","ов"),n},noResults:function(){return"Совпадений не найдено"},searching:function(){return"Поиск…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/sk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sk",[],function(){var e={2:function(e){return e?"dva":"dve"},3:function(){return"tri"},4:function(){return"štyri"}};return{inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?"Prosím, zadajte o jeden znak menej":n>=2&&n<=4?"Prosím, zadajte o "+e[n](!0)+" znaky menej":"Prosím, zadajte o "+n+" znakov menej"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?"Prosím, zadajte ešte jeden znak":n<=4?"Prosím, zadajte ešte ďalšie "+e[n](!0)+" znaky":"Prosím, zadajte ešte ďalších "+n+" znakov"},loadingMore:function(){return"Loading more results…"},maximumSelected:function(t){return t.maximum==1?"Môžete zvoliť len jednu položku":t.maximum>=2&&t.maximum<=4?"Môžete zvoliť najviac "+e[t.maximum](!1)+" položky":"Môžete zvoliť najviac "+t.maximum+" položiek"},noResults:function(){return"Nenašli sa žiadne položky"},searching:function(){return"Vyhľadávanie…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/sl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sl",[],function(){return{errorLoading:function(){return"Zadetkov iskanja ni bilo mogoče naložiti."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Prosim zbrišite "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Prosim vpišite še "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},loadingMore:function(){return"Nalagam več zadetkov…"},maximumSelected:function(e){var n="Označite lahko največ "+e.maximum+" predmet";return 2==e.maximum?n+="a":1!=e.maximum&&(n+="e"),n},noResults:function(){return"Ni zadetkov."},searching:function(){return"Iščem…"},removeAllItems:function(){return"Odstranite vse elemente"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/sq.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sq",[],function(){return{errorLoading:function(){return"Rezultatet nuk mund të ngarkoheshin."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Të lutem fshi "+n+" karakter";return 1!=n&&(t+="e"),t},inputTooShort:function(e){return"Të lutem shkruaj "+(e.minimum-e.input.length)+" ose më shumë karaktere"},loadingMore:function(){return"Duke ngarkuar më shumë rezultate…"},maximumSelected:function(e){var n="Mund të zgjedhësh vetëm "+e.maximum+" element";return 1!=e.maximum&&(n+="e"),n},noResults:function(){return"Nuk u gjet asnjë rezultat"},searching:function(){return"Duke kërkuar…"},removeAllItems:function(){return"Hiq të gjitha sendet"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/sr-Cyrl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sr-Cyrl",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Преузимање није успело."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Обришите "+n+" симбол";return r+=e(n,"","а","а"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Укуцајте бар још "+n+" симбол";return r+=e(n,"","а","а"),r},loadingMore:function(){return"Преузимање још резултата…"},maximumSelected:function(t){var n="Можете изабрати само "+t.maximum+" ставк";return n+=e(t.maximum,"у","е","и"),n},noResults:function(){return"Ништа није пронађено"},searching:function(){return"Претрага…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/sr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sr",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Preuzimanje nije uspelo."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Obrišite "+n+" simbol";return r+=e(n,"","a","a"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Ukucajte bar još "+n+" simbol";return r+=e(n,"","a","a"),r},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(t){var n="Možete izabrati samo "+t.maximum+" stavk";return n+=e(t.maximum,"u","e","i"),n},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/sv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sv",[],function(){return{errorLoading:function(){return"Resultat kunde inte laddas."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vänligen sudda ut "+t+" tecken";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vänligen skriv in "+t+" eller fler tecken";return n},loadingMore:function(){return"Laddar fler resultat…"},maximumSelected:function(e){var t="Du kan max välja "+e.maximum+" element";return t},noResults:function(){return"Inga träffar"},searching:function(){return"Söker…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/th.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/th",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="โปรดลบออก "+t+" ตัวอักษร";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="โปรดพิมพ์เพิ่มอีก "+t+" ตัวอักษร";return n},loadingMore:function(){return"กำลังค้นข้อมูลเพิ่ม…"},maximumSelected:function(e){var t="คุณสามารถเลือกได้ไม่เกิน "+e.maximum+" รายการ";return t},noResults:function(){return"ไม่พบข้อมูล"},searching:function(){return"กำลังค้นข้อมูล…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/tk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/tk",[],function(){return{errorLoading:function(){return"Netije ýüklenmedi."},inputTooLong:function(e){return e.input.length-e.maximum+" harp bozuň."},inputTooShort:function(e){return"Ýene-de iň az "+(e.minimum-e.input.length)+" harp ýazyň."},loadingMore:function(){return"Köpräk netije görkezilýär…"},maximumSelected:function(e){return"Diňe "+e.maximum+" sanysyny saýlaň."},noResults:function(){return"Netije tapylmady."},searching:function(){return"Gözlenýär…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/tr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/tr",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" karakter daha girmelisiniz";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="En az "+t+" karakter daha girmelisiniz";return n},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(e){var t="Sadece "+e.maximum+" seçim yapabilirsiniz";return t},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/uk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/uk",[],function(){function e(e,t,n,r){return e%100>10&&e%100<15?r:e%10===1?t:e%10>1&&e%10<5?n:r}return{errorLoading:function(){return"Неможливо завантажити результати"},inputTooLong:function(t){var n=t.input.length-t.maximum;return"Будь ласка, видаліть "+n+" "+e(t.maximum,"літеру","літери","літер")},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Будь ласка, введіть "+t+" або більше літер"},loadingMore:function(){return"Завантаження інших результатів…"},maximumSelected:function(t){return"Ви можете вибрати лише "+t.maximum+" "+e(t.maximum,"пункт","пункти","пунктів")},noResults:function(){return"Нічого не знайдено"},searching:function(){return"Пошук…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/vi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/vi",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vui lòng nhập ít hơn "+t+" ký tự";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vui lòng nhập nhiều hơn "+t+' ký tự"';return n},loadingMore:function(){return"Đang lấy thêm kết quả…"},maximumSelected:function(e){var t="Chỉ có thể chọn được "+e.maximum+" lựa chọn";return t},noResults:function(){return"Không tìm thấy kết quả"},searching:function(){return"Đang tìm…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/zh-CN.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="请删除"+t+"个字符";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="请再输入至少"+t+"个字符";return n},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(e){var t="最多只能选择"+e.maximum+"个项目";return t},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/select2/i18n/zh-TW.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="請刪掉"+t+"個字元";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="請再輸入"+t+"個字元";return n},loadingMore:function(){return"載入中…"},maximumSelected:function(e){var t="你只能選擇最多"+e.maximum+"項";return t},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /static/admin/js/vendor/xregexp/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2007-2012 Steven Levithan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /static/all_pages.py: -------------------------------------------------------------------------------- 1 | PAGES = [ 2 | { 3 | 'app': 'noq', 4 | 'name':'Home', # the title of the webpage 5 | 'path': '/..', # (absolute) path to page for links 6 | 'address': '', # django address of page 7 | 'template_path': './noq.html', # path in templates/ to template file 8 | }, 9 | ] -------------------------------------------------------------------------------- /static/mathjax-import.js: -------------------------------------------------------------------------------- 1 | var script = document.createElement('script'); 2 | script.src = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js"; 3 | document.head.appendChild(script); 4 | 5 | MathJax.Hub.Config({ 6 | jax: ["input/TeX", "output/HTML-CSS"], 7 | extensions: ["tex2jax.js"], 8 | "HTML-CSS": { preferredFont: "TeX", availableFonts: ["STIX","TeX"] }, 9 | tex2jax: { inlineMath: [ ["$", "$"], ["\\(","\\)"] ], displayMath: [ ["$$","$$"], ["\\[", "\\]"] ], processEscapes: true, ignoreClass: "tex2jax_ignore|dno" }, 10 | TeX: { noUndefined: { attributes: { mathcolor: "red", mathbackground: "#FFEEEE", mathsize: "90%" } } }, 11 | messageStyle: "none" 12 | }); -------------------------------------------------------------------------------- /static/noq/images/+.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/+.png -------------------------------------------------------------------------------- /static/noq/images/+x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/+x.png -------------------------------------------------------------------------------- /static/noq/images/-.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/-.png -------------------------------------------------------------------------------- /static/noq/images/-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/-b.png -------------------------------------------------------------------------------- /static/noq/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/1.png -------------------------------------------------------------------------------- /static/noq/images/1b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/1b.png -------------------------------------------------------------------------------- /static/noq/images/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/7.png -------------------------------------------------------------------------------- /static/noq/images/7b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/7b.png -------------------------------------------------------------------------------- /static/noq/images/=.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/=.png -------------------------------------------------------------------------------- /static/noq/images/J.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/J.png -------------------------------------------------------------------------------- /static/noq/images/Jb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/Jb.png -------------------------------------------------------------------------------- /static/noq/images/L.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/L.png -------------------------------------------------------------------------------- /static/noq/images/Lb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/Lb.png -------------------------------------------------------------------------------- /static/noq/images/battleship_bottom_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/battleship_bottom_end.png -------------------------------------------------------------------------------- /static/noq/images/battleship_left_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/battleship_left_end.png -------------------------------------------------------------------------------- /static/noq/images/battleship_right_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/battleship_right_end.png -------------------------------------------------------------------------------- /static/noq/images/battleship_top_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/battleship_top_end.png -------------------------------------------------------------------------------- /static/noq/images/battleship_water.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/battleship_water.png -------------------------------------------------------------------------------- /static/noq/images/bl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/bl.png -------------------------------------------------------------------------------- /static/noq/images/black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/black.png -------------------------------------------------------------------------------- /static/noq/images/black_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/black_circle.png -------------------------------------------------------------------------------- /static/noq/images/bottom-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/bottom-left.png -------------------------------------------------------------------------------- /static/noq/images/bottom-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/bottom-right.png -------------------------------------------------------------------------------- /static/noq/images/bottom_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/bottom_end.png -------------------------------------------------------------------------------- /static/noq/images/br.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/br.png -------------------------------------------------------------------------------- /static/noq/images/brbl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/brbl.png -------------------------------------------------------------------------------- /static/noq/images/bulb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/bulb.png -------------------------------------------------------------------------------- /static/noq/images/center_dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/center_dot.png -------------------------------------------------------------------------------- /static/noq/images/down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/down_arrow.png -------------------------------------------------------------------------------- /static/noq/images/e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/e.png -------------------------------------------------------------------------------- /static/noq/images/large_black_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/large_black_circle.png -------------------------------------------------------------------------------- /static/noq/images/left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/left_arrow.png -------------------------------------------------------------------------------- /static/noq/images/left_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/left_end.png -------------------------------------------------------------------------------- /static/noq/images/moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/moon.png -------------------------------------------------------------------------------- /static/noq/images/n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/n.png -------------------------------------------------------------------------------- /static/noq/images/ne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/ne.png -------------------------------------------------------------------------------- /static/noq/images/negative_wide_down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/negative_wide_down_arrow.png -------------------------------------------------------------------------------- /static/noq/images/negative_wide_left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/negative_wide_left_arrow.png -------------------------------------------------------------------------------- /static/noq/images/negative_wide_right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/negative_wide_right_arrow.png -------------------------------------------------------------------------------- /static/noq/images/negative_wide_up_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/negative_wide_up_arrow.png -------------------------------------------------------------------------------- /static/noq/images/nw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/nw.png -------------------------------------------------------------------------------- /static/noq/images/r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/r.png -------------------------------------------------------------------------------- /static/noq/images/rb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/rb.png -------------------------------------------------------------------------------- /static/noq/images/right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/right_arrow.png -------------------------------------------------------------------------------- /static/noq/images/right_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/right_end.png -------------------------------------------------------------------------------- /static/noq/images/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/s.png -------------------------------------------------------------------------------- /static/noq/images/se.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/se.png -------------------------------------------------------------------------------- /static/noq/images/sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/sw.png -------------------------------------------------------------------------------- /static/noq/images/tent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tent.png -------------------------------------------------------------------------------- /static/noq/images/tl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tl.png -------------------------------------------------------------------------------- /static/noq/images/tlbl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tlbl.png -------------------------------------------------------------------------------- /static/noq/images/tlbr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tlbr.png -------------------------------------------------------------------------------- /static/noq/images/tlbrbl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tlbrbl.png -------------------------------------------------------------------------------- /static/noq/images/tltr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tltr.png -------------------------------------------------------------------------------- /static/noq/images/tltrbl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tltrbl.png -------------------------------------------------------------------------------- /static/noq/images/tltrbr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tltrbr.png -------------------------------------------------------------------------------- /static/noq/images/tltrbrbl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tltrbrbl.png -------------------------------------------------------------------------------- /static/noq/images/top-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/top-left.png -------------------------------------------------------------------------------- /static/noq/images/top-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/top-right.png -------------------------------------------------------------------------------- /static/noq/images/top_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/top_end.png -------------------------------------------------------------------------------- /static/noq/images/tr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tr.png -------------------------------------------------------------------------------- /static/noq/images/trbl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/trbl.png -------------------------------------------------------------------------------- /static/noq/images/trbr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/trbr.png -------------------------------------------------------------------------------- /static/noq/images/trbrbl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/trbrbl.png -------------------------------------------------------------------------------- /static/noq/images/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/tree.png -------------------------------------------------------------------------------- /static/noq/images/unused/+w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/unused/+w.png -------------------------------------------------------------------------------- /static/noq/images/unused/-w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/unused/-w.png -------------------------------------------------------------------------------- /static/noq/images/unused/1w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/unused/1w.png -------------------------------------------------------------------------------- /static/noq/images/unused/7w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/unused/7w.png -------------------------------------------------------------------------------- /static/noq/images/unused/Jw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/unused/Jw.png -------------------------------------------------------------------------------- /static/noq/images/unused/Lo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/unused/Lo.png -------------------------------------------------------------------------------- /static/noq/images/unused/rw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/unused/rw.png -------------------------------------------------------------------------------- /static/noq/images/up_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/up_arrow.png -------------------------------------------------------------------------------- /static/noq/images/w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/w.png -------------------------------------------------------------------------------- /static/noq/images/white_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/white_circle.png -------------------------------------------------------------------------------- /static/noq/images/white_circle_d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/white_circle_d.png -------------------------------------------------------------------------------- /static/noq/images/white_circle_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/white_circle_l.png -------------------------------------------------------------------------------- /static/noq/images/white_circle_r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/white_circle_r.png -------------------------------------------------------------------------------- /static/noq/images/white_circle_u.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/white_circle_u.png -------------------------------------------------------------------------------- /static/noq/images/wide_down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/wide_down_arrow.png -------------------------------------------------------------------------------- /static/noq/images/wide_left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/wide_left_arrow.png -------------------------------------------------------------------------------- /static/noq/images/wide_right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/wide_right_arrow.png -------------------------------------------------------------------------------- /static/noq/images/wide_up_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/wide_up_arrow.png -------------------------------------------------------------------------------- /static/noq/images/‖.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/‖.png -------------------------------------------------------------------------------- /static/noq/images/←.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/←.png -------------------------------------------------------------------------------- /static/noq/images/←b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/←b.png -------------------------------------------------------------------------------- /static/noq/images/↑.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/↑.png -------------------------------------------------------------------------------- /static/noq/images/↑b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/↑b.png -------------------------------------------------------------------------------- /static/noq/images/→.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/→.png -------------------------------------------------------------------------------- /static/noq/images/→b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/→b.png -------------------------------------------------------------------------------- /static/noq/images/↓.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/↓.png -------------------------------------------------------------------------------- /static/noq/images/↓b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/↓b.png -------------------------------------------------------------------------------- /static/noq/images/↰.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/↰.png -------------------------------------------------------------------------------- /static/noq/images/↱.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/↱.png -------------------------------------------------------------------------------- /static/noq/images/↲.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/↲.png -------------------------------------------------------------------------------- /static/noq/images/↳.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/↳.png -------------------------------------------------------------------------------- /static/noq/images/↴.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/↴.png -------------------------------------------------------------------------------- /static/noq/images/⬏.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/⬏.png -------------------------------------------------------------------------------- /static/noq/images/⬐.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/⬐.png -------------------------------------------------------------------------------- /static/noq/images/⬑.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mstang107/noq/fced51566e4af163cd40b3c6b8900912240199be/static/noq/images/⬑.png -------------------------------------------------------------------------------- /static/noq/noq_recycle_bin.txt: -------------------------------------------------------------------------------- 1 | 2 | // class NagareElf extends Elf 3 | // { 4 | // static controls() 5 | // { 6 | // let controls = super.controls(); 7 | // controls['[URDL]'] = 'Put black (path) arrow'; 8 | // controls['Shift + [URDL]'] = 'Put white (wind) arrow'; 9 | // return controls; 10 | // } 11 | 12 | // constructor(elt) 13 | // { 14 | // super(elt); 15 | // this.dict = { 16 | // 'u': 'wide_up_arrow.png', 17 | // 'r': 'wide_right_arrow.png', 18 | // 'd': 'wide_down_arrow.png', 19 | // 'l': 'wide_left_arrow.png', 20 | // 'U': 'negative_wide_up_arrow.png', 21 | // 'R': 'negative_wide_right_arrow.png', 22 | // 'D': 'negative_wide_down_arrow.png', 23 | // 'L': 'negative_wide_left_arrow.png' 24 | // } 25 | // } 26 | // handle_input(key, modifiers) 27 | // { 28 | // super.handle_input(key, modifiers); 29 | 30 | // if (key == 'x') 31 | // { 32 | // this.key = 'black'; 33 | // this.puzzle_elt.style.backgroundColor = 'black'; 34 | // } 35 | 36 | // else if (this.dict[key]) 37 | // { 38 | // this.key = key; 39 | // this.puzzle_elt.style.backgroundImage = image_url(this.dict[key]); 40 | // } 41 | // } 42 | // load_example(str) 43 | // { 44 | // this.key = str; 45 | // if (str == 'black') 46 | // this.puzzle_elt.style.backgroundColor = 'black'; 47 | // else 48 | // this.puzzle_elt.style.backgroundImage = image_url(this.dict[str]); 49 | // } 50 | // encode_input() 51 | // { 52 | // return this.key; 53 | // } 54 | // } 55 | 56 | 57 | 58 | // class IntElf extends Elf 59 | // { 60 | // static controls() 61 | // { 62 | // let controls = super.controls(); 63 | // controls['[0-9]'] = 'Write clue in cell'; 64 | // return controls; 65 | // } 66 | 67 | // handle_input(key, modifiers) 68 | // { 69 | // super.handle_input(key, modifiers); 70 | 71 | // if (!'1234567890'.includes(key)) return; 72 | // let num = parseInt(this.puzzle_elt.innerHTML + key); 73 | // if (num > 99) 74 | // num = key; 75 | // this.puzzle_elt.innerHTML = num+''; 76 | // } 77 | 78 | // encode_input() 79 | // { 80 | // return this.puzzle_elt.innerHTML ? this.puzzle_elt.innerHTML : null; 81 | // } 82 | // } 83 | -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | h2 2 | { 3 | margin-left: -10px; 4 | margin-bottom: 15px; 5 | margin-top: 0px; 6 | } 7 | 8 | html * 9 | { 10 | font-family: Arial; 11 | } 12 | 13 | .section 14 | { 15 | margin: auto; 16 | width: 70%; 17 | padding: 5px; 18 | } 19 | 20 | .puz 21 | { 22 | width: 80%; 23 | margin-left: auto; 24 | margin-right: auto; 25 | margin-top: 10px; 26 | margin-bottom: 10px; 27 | border-spacing: 10px; 28 | } 29 | 30 | .puz tr 31 | { 32 | padding-bottom: 10px; 33 | } 34 | .puz td 35 | { 36 | vertical-align: bottom; 37 | } 38 | 39 | .row 40 | { 41 | display: flex; 42 | flex-direction: row; 43 | justify-content: center; 44 | margin-left: 15px; 45 | margin-right: 15px; 46 | margin-bottom: 25px; 47 | padding: 5px; 48 | } 49 | 50 | .row > .smallhalfrow 51 | { 52 | width: 200px; 53 | margin-right: 15px; 54 | } 55 | 56 | .row > .largehalfrow 57 | { 58 | margin-left: 15px; 59 | margin-top: -20px; 60 | width: 60%; 61 | } 62 | 63 | .figure 64 | { 65 | display: block; 66 | margin-left: auto; 67 | margin-right: auto; 68 | margin-bottom: 5px; 69 | width: min(90%,200px); 70 | } 71 | 72 | .caption 73 | { 74 | font-size: 0.8em; 75 | font-style: italic; 76 | text-align: center; 77 | } 78 | 79 | .header 80 | { 81 | display: flex; 82 | flex-direction: row; 83 | text-align: center; 84 | width: 50%; 85 | margin: auto; 86 | } 87 | 88 | .header div 89 | { 90 | margin: auto; 91 | } 92 | 93 | .header li 94 | { 95 | display: inline; 96 | margin-left: 10px; 97 | margin-right: 10px; 98 | padding-left: 5px; 99 | padding-right: 5px; 100 | padding-top: 2px; 101 | padding-bottom: 2px; 102 | } 103 | 104 | .header hr 105 | { 106 | margin-top: -10px; 107 | margin-bottom: 25px; 108 | } 109 | 110 | .header .active::before 111 | { 112 | content: '['; 113 | } 114 | 115 | .header .active::after 116 | { 117 | content: ']'; 118 | } 119 | 120 | #typegroups 121 | { 122 | display: grid; 123 | grid-template-columns: 1fr 1fr 1fr; 124 | } 125 | 126 | .typegroup 127 | { 128 | border: 1px solid black; 129 | margin: 10px; 130 | padding: 10px; 131 | min-width: 25%; 132 | } -------------------------------------------------------------------------------- /static/utils.py: -------------------------------------------------------------------------------- 1 | def add_dicts(dict1, dict2): 2 | return {**dict1, **dict2} -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% load static %} 5 | {% block head %} 6 | 7 | 8 | {% endblock %} 9 | {% block title %}Home{% endblock %} 10 | 11 | 12 | {% block content %} 13 | TODO add content here 14 | {% endblock %} 15 | 16 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | 5 | {% block title %}Noq{% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 | Noq - logic puzzle solver
11 | 12 | by 13 | Jenna 14 | and 15 | Michael 16 | using 17 | claspy
18 |
19 |
20 | 21 |
22 | {% for cat, cat_name in cats.items %} 23 |
24 | {{ cat_name }} 25 |
    26 | {% for cat0, cat0_types in types.items %} 27 | {% if cat0 == cat %} 28 | {% for pt_dict in cat0_types %} 29 |
  • {{ pt_dict.name }}
  • 30 | {% endfor %} 31 | {% endif %} 32 | {% endfor %} 33 |
34 |
35 | {% endfor %} 36 |
37 | 38 |
39 | 40 |
41 | © 2023; 42 | general layout of this page borrowed from puzz.link 43 |
44 |
45 | {% endblock %} -------------------------------------------------------------------------------- /templates/noq.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% block head %} 3 | {{ block.super }} 4 | {% load static %} 5 | 6 | {% endblock %} 7 | {% block title %}{{ name }} solver - Noq{% endblock %} 8 | {% block content %} 9 |
10 |
11 | {{ name }} solver 12 |
13 | 14 |
15 |
16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 |
24 | 25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | 36 | 37 |
38 | 41 | 42 | 43 |
44 |
Back
45 | {% endblock %} -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # Testing instructions 2 | 3 | From the root folder (`noq/`, not this directory), run `python -m test.test` to test all puzzles. 4 | 5 | To test a subset of puzzles, supply the names (IDs) of the puzzles at the end, e.g. `python -m test.test easyas tll`. 6 | 7 | Expect a bunch of stuff to get printed to your terminal as the solvers run; test results will appear at the very end. -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | # This file needs to exist, but it can be blank. --------------------------------------------------------------------------------