10 Commits

22 changed files with 267 additions and 222 deletions

2
.gitignore vendored
View File

@ -1,5 +1,3 @@
.DS_Store .DS_Store
._.DS_Store ._.DS_Store
*.class *.class
wordsearch.war
wordsearch.jar

21
LICENSE
View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2018 Matthew Slowe
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,34 +0,0 @@
JAVA = /usr/bin/java
LIBS = .:war/WEB-INF/lib/commons-lang.jar:war/WEB-INF/lib/sqlite-jdbc.jar
JAVAC = /usr/bin/javac
JFLAGS = -g -classpath $(LIBS)
SRCS = uk/org/mafoo/wordsearch/CouldNotPlaceWordException.java \
uk/org/mafoo/wordsearch/Bounds.java \
uk/org/mafoo/wordsearch/GridFactory.java \
uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java \
uk/org/mafoo/wordsearch/Direction.java
JSPS = $(wildcard war/*.jsp war/*.css war/WEB-INF/jspf/*.jspf)
OBJS = ${SRCS:.java=.class}
.SUFFIXES: .java .class
.PHONY: default clean
default: wordsearch.war
clean:
rm -f $(OBJS) wordsearch.jar wordsearch.war
.java.class:
$(JAVAC) $(JFLAGS) $<
wordsearch.jar: $(OBJS)
jar cf $@ $(OBJS)
war/WEB-INF/lib/wordsearch.jar: wordsearch.jar
cp $< $@
wordsearch.war: war/WEB-INF/lib/wordsearch.jar $(JSPS)
jar -cvf $@ -C war .

91
counties.txt Executable file
View File

@ -0,0 +1,91 @@
Aberdeenshire
Anglesey
Angus
Antrim
Argyll
Armagh
Ayrshire
Banffshire
Bedfordshire
Berkshire
Berwickshire
Brecknockshire
Buckinghamshire
Buteshire
Caernarfonshire
Caithness
Cambridgeshire
Cardiganshire
Carmarthenshire
Cheshire
Clackmannanshire
Cornwall
Cromartyshire
Cumberland
Denbighshire
Derbyshire
Devon
Dorset
Down
Dumbartonshire
Dumfriesshire
Durham
East Lothian
Essex
Fermanagh
Fife
Flintshire
Glamorgan
Gloucestershire
Hampshire
Herefordshire
Hertfordshire
Huntingdonshire
Invernessshire
Kent
Kincardineshire
Kirkcudbrightshire
Lanarkshire
Lancashire
Leicestershire
Lincolnshire
Londonderry
Merionethshire
Middlesex
Midlothian
Monmouthshire
Montgomeryshire
Morayshire
Nairnshire
Norfolk
Northamptonshire
Northumberland
Nottinghamshire
Orkney
Oxfordshire
Peeblesshire
Pembrokeshire
Perthshire
Radnorshire
Renfrewshire
Rossshire
Roxburghshire
Rutland
Selkirkshire
Shetland
Shropshire
Somerset
Staffordshire
Stirlingshire
Suffolk
Surrey
Sussex
Sutherland
Tyrone
Warwickshire
West Lothian
Westmorland
Wigtownshire
Wiltshire
Worcestershire
Yorkshire

View File

@ -1 +0,0 @@
CREATE TABLE grids (id integer primary key, ts timestamp default current_timestamp, remotehost varchar, input, size_x int, size_y int, simple tinyint, result varchar);

52
tags Executable file
View File

@ -0,0 +1,52 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.9~svn20110310 //
Bounds uk/org/mafoo/wordsearch/Bounds.java /^ protected Bounds(int min_y, int max_y, int min_x, int max_x) {$/;" m class:Bounds
Bounds uk/org/mafoo/wordsearch/Bounds.java /^class Bounds {$/;" c
CouldNotPlaceWordException uk/org/mafoo/wordsearch/CouldNotPlaceWordException.java /^ protected CouldNotPlaceWordException() {$/;" m class:CouldNotPlaceWordException
CouldNotPlaceWordException uk/org/mafoo/wordsearch/CouldNotPlaceWordException.java /^class CouldNotPlaceWordException extends Exception {$/;" c
Direction uk/org/mafoo/wordsearch/Direction.java /^enum Direction { N, NE, E, SE, S, SW, W, NW; };$/;" g
DistributedRandomNumberGenerator uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java /^ public DistributedRandomNumberGenerator() {$/;" m class:DistributedRandomNumberGenerator
DistributedRandomNumberGenerator uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java /^public class DistributedRandomNumberGenerator {$/;" c
E uk/org/mafoo/wordsearch/Direction.java /^enum Direction { N, NE, E, SE, S, SW, W, NW; };$/;" e enum:Direction file:
GridFactory uk/org/mafoo/wordsearch/GridFactory.java /^public class GridFactory {$/;" c
MAX_TRIES uk/org/mafoo/wordsearch/GridFactory.java /^ static final int MAX_TRIES = 500;$/;" f class:GridFactory
N uk/org/mafoo/wordsearch/Direction.java /^enum Direction { N, NE, E, SE, S, SW, W, NW; };$/;" e enum:Direction file:
NE uk/org/mafoo/wordsearch/Direction.java /^enum Direction { N, NE, E, SE, S, SW, W, NW; };$/;" e enum:Direction file:
NW uk/org/mafoo/wordsearch/Direction.java /^enum Direction { N, NE, E, SE, S, SW, W, NW; };$/;" e enum:Direction file:
S uk/org/mafoo/wordsearch/Direction.java /^enum Direction { N, NE, E, SE, S, SW, W, NW; };$/;" e enum:Direction file:
SE uk/org/mafoo/wordsearch/Direction.java /^enum Direction { N, NE, E, SE, S, SW, W, NW; };$/;" e enum:Direction file:
SW uk/org/mafoo/wordsearch/Direction.java /^enum Direction { N, NE, E, SE, S, SW, W, NW; };$/;" e enum:Direction file:
W uk/org/mafoo/wordsearch/Direction.java /^enum Direction { N, NE, E, SE, S, SW, W, NW; };$/;" e enum:Direction file:
addNumber uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java /^ public void addNumber(int value, double distribution) {$/;" m class:DistributedRandomNumberGenerator
chars uk/org/mafoo/wordsearch/GridFactory.java /^ private static char[] chars = new char[] {$/;" f class:GridFactory file:
clone2d uk/org/mafoo/wordsearch/GridFactory.java /^ private static char[][] clone2d(char[][] source) {$/;" m class:GridFactory file:
directions uk/org/mafoo/wordsearch/GridFactory.java /^ private static Direction[] directions = new Direction[] { Direction.N, Direction.NE, Direction.E, Direction.SE, Direction.S, Direction.SW, Direction.W, Direction.NW };$/;" f class:GridFactory file:
distSum uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java /^ private double distSum;$/;" f class:DistributedRandomNumberGenerator file:
distribution uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java /^ private HashMap<Integer, Double> distribution;$/;" f class:DistributedRandomNumberGenerator file:
drng uk/org/mafoo/wordsearch/GridFactory.java /^ static DistributedRandomNumberGenerator drng = new DistributedRandomNumberGenerator();$/;" f class:GridFactory
dump2d uk/org/mafoo/wordsearch/GridFactory.java /^ private static void dump2d(char[][] g) {$/;" m class:GridFactory file:
getBounds uk/org/mafoo/wordsearch/GridFactory.java /^ private static Bounds getBounds(int height, int width, Direction direction, int length) {$/;" m class:GridFactory file:
getDirection uk/org/mafoo/wordsearch/GridFactory.java /^ private static Direction getDirection(boolean simple) {$/;" m class:GridFactory file:
getDistributedRandomNumber uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java /^ public int getDistributedRandomNumber() {$/;" m class:DistributedRandomNumberGenerator
getRandomChar uk/org/mafoo/wordsearch/GridFactory.java /^ private static char getRandomChar() {$/;" m class:GridFactory file:
main uk/org/mafoo/wordsearch/GridFactory.java /^ public static void main(String[] args) throws IOException {$/;" m class:GridFactory
makeGrid uk/org/mafoo/wordsearch/GridFactory.java /^ public static char[][] makeGrid(List<String> words, int height, int width) {$/;" m class:GridFactory
makeGrid uk/org/mafoo/wordsearch/GridFactory.java /^ public static char[][] makeGrid(List<String> words, int height, int width, boolean simple) {$/;" m class:GridFactory
max_x uk/org/mafoo/wordsearch/Bounds.java /^ int max_x;$/;" f class:Bounds
max_y uk/org/mafoo/wordsearch/Bounds.java /^ int max_y;$/;" f class:Bounds
min_x uk/org/mafoo/wordsearch/Bounds.java /^ int min_x;$/;" f class:Bounds
min_y uk/org/mafoo/wordsearch/Bounds.java /^ int min_y;$/;" f class:Bounds
move_x uk/org/mafoo/wordsearch/GridFactory.java /^ private static int move_x(int x, Direction d) {$/;" m class:GridFactory file:
move_y uk/org/mafoo/wordsearch/GridFactory.java /^ private static int move_y(int y, Direction d) {$/;" m class:GridFactory file:
placeWord uk/org/mafoo/wordsearch/GridFactory.java /^ private static char[][] placeWord(String word, char[][] grid, boolean simple) throws CouldNotPlaceWordException {$/;" m class:GridFactory file:
rnd uk/org/mafoo/wordsearch/GridFactory.java /^ static Random rnd = new Random();$/;" f class:GridFactory
toString uk/org/mafoo/wordsearch/Bounds.java /^ public String toString() {$/;" m class:Bounds
uk.org.mafoo.wordsearch uk/org/mafoo/wordsearch/Bounds.java /^package uk.org.mafoo.wordsearch;$/;" p
uk.org.mafoo.wordsearch uk/org/mafoo/wordsearch/CouldNotPlaceWordException.java /^package uk.org.mafoo.wordsearch;$/;" p
uk.org.mafoo.wordsearch uk/org/mafoo/wordsearch/Direction.java /^package uk.org.mafoo.wordsearch;$/;" p
uk.org.mafoo.wordsearch uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java /^package uk.org.mafoo.wordsearch;$/;" p
uk.org.mafoo.wordsearch uk/org/mafoo/wordsearch/GridFactory.java /^package uk.org.mafoo.wordsearch;$/;" p

View File

@ -1,9 +0,0 @@
Kitchen
Lounge
Study
Ballroom
Conservatory
Billiard Room
Library
Hall
Dining Room

View File

@ -6,7 +6,7 @@ import java.util.*;
public class GridFactory { public class GridFactory {
static Random rnd = new Random(); static Random rnd = new Random();
static final int MAX_TRIES = 5000; static final int MAX_TRIES = 500;
/* https://www.math.cornell.edu/~mec/2003-2004/cryptography/subs/frequencies.html */ /* https://www.math.cornell.edu/~mec/2003-2004/cryptography/subs/frequencies.html */
static DistributedRandomNumberGenerator drng = new DistributedRandomNumberGenerator(); static DistributedRandomNumberGenerator drng = new DistributedRandomNumberGenerator();
@ -37,7 +37,7 @@ public class GridFactory {
drng.addNumber(23, 0.0017d); // X drng.addNumber(23, 0.0017d); // X
drng.addNumber(24, 0.0211d); // Y drng.addNumber(24, 0.0211d); // Y
drng.addNumber(25, 0.0007d); // Z drng.addNumber(25, 0.0007d); // Z
} }
private static char[] chars = new char[] { private static char[] chars = new char[] {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
@ -61,8 +61,8 @@ public class GridFactory {
} }
private static Direction[] directions = new Direction[] { Direction.N, Direction.NE, Direction.E, Direction.SE, Direction.S, Direction.SW, Direction.W, Direction.NW }; private static Direction[] directions = new Direction[] { Direction.N, Direction.NE, Direction.E, Direction.SE, Direction.S, Direction.SW, Direction.W, Direction.NW };
private static Direction getDirection(boolean simple) { private static Direction getDirection(Modes mode) {
if(simple) { if(mode == Modes.SIMPLE || mode == Modes.CROSSWORD) {
return rnd.nextBoolean() ? Direction.E : Direction.S; return rnd.nextBoolean() ? Direction.E : Direction.S;
} else { } else {
return directions[rnd.nextInt(directions.length-1)]; return directions[rnd.nextInt(directions.length-1)];
@ -77,10 +77,10 @@ public class GridFactory {
Bounds b = new Bounds(0, height, 0, width); Bounds b = new Bounds(0, height, 0, width);
length--; // arrays, duh length--; // arrays, duh
if( if(
direction == Direction.N || direction == Direction.N ||
direction == Direction.NE || direction == Direction.NE ||
direction == Direction.NW direction == Direction.NW
) { ) {
b.min_y = length; b.min_y = length;
@ -158,10 +158,6 @@ public class GridFactory {
return makeGrid(words, height, width, false, true); return makeGrid(words, height, width, false, true);
} }
public static char[][] makeGrid(List<String> words, int height, int width, boolean simple) {
return makeGrid(words, height, width, simple, true);
}
public static char[][] makeGrid(List<String> words, int height, int width, boolean simple, boolean fill) { public static char[][] makeGrid(List<String> words, int height, int width, boolean simple, boolean fill) {
char[][] grid = new char[height][width]; char[][] grid = new char[height][width];
@ -170,7 +166,7 @@ public class GridFactory {
int tries = 0; int tries = 0;
while(true) { while(true) {
try { try {
grid = placeWord(word, grid, simple); grid = placeWord(word, grid, mode);
break; break;
} catch (CouldNotPlaceWordException e) { } catch (CouldNotPlaceWordException e) {
if(tries > MAX_TRIES) { if(tries > MAX_TRIES) {
@ -184,11 +180,11 @@ public class GridFactory {
} }
} }
// Fill rest of grid if(mode != Modes.CROSSWORD) {
if(fill) { // Fill rest of grid
for (int y=0; y<height; y++) { for (int y=0; y<height; y++) {
for (int x=0; x<width; x++) { for (int x=0; x<width; x++) {
if (grid[y][x] == Character.UNASSIGNED) if (grid[y][x] == Character.UNASSIGNED)
// grid[y][x] = '_'; // grid[y][x] = '_';
grid[y][x] = getRandomChar(); grid[y][x] = getRandomChar();
} }
@ -198,17 +194,18 @@ public class GridFactory {
return grid; return grid;
} }
private static char[][] placeWord(String word, char[][] grid, boolean simple) throws CouldNotPlaceWordException { private static char[][] placeWord(String word, char[][] grid, Modes mode) throws CouldNotPlaceWordException {
Direction direction = getDirection(simple); Direction direction = getDirection(mode);
Bounds b = getBounds(grid.length, grid[0].length, direction, word.length()); Bounds b = getBounds(grid.length, grid[0].length, direction, word.length());
// System.out.println("[" + word + "] bounds: " + b); // System.out.println("[" + word + "] bounds: " + b);
int x = rnd.nextInt(b.max_x - b.min_x) + b.min_x; int x = rnd.nextInt(b.max_x - b.min_x) + b.min_x;
int y = rnd.nextInt(b.max_y - b.min_y) + b.min_y; int y = rnd.nextInt(b.max_y - b.min_y) + b.min_y;
// System.out.println("[" + word + "] Placing @ " + x + "," + y + " going " + direction); // System.out.println("[" + word + "] Placing @ " + x + "," + y + " going " + direction);
char[][] tempgrid = clone2d(grid); char[][] tempgrid = clone2d(grid);
for( char c : word.toUpperCase().toCharArray() ) { for( char c : word.toUpperCase().toCharArray() ) {
if(!Character.isLetter(c)) continue; if(!Character.isLetter(c)) continue;
if(grid[y][x] != Character.UNASSIGNED) { if(grid[y][x] != Character.UNASSIGNED) {
if (grid[y][x] != c) { if (grid[y][x] != c) {
@ -220,7 +217,7 @@ public class GridFactory {
tempgrid[y][x] = c; tempgrid[y][x] = c;
x = move_x(x, direction); x = move_x(x, direction);
y = move_y(y, direction); y = move_y(y, direction);
} }
return tempgrid; return tempgrid;
} }

View File

@ -0,0 +1,7 @@
package uk.org.mafoo.wordsearch;
public enum Modes {
NORMAL,
SIMPLE,
CROSSWORD;
}

View File

@ -0,0 +1,22 @@
package uk.org.mafoo.wordsearch;
import java.sql.*;
class Store {
Connection conn = null;
protected Store(String dbfile) {
try {
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:" + dbfile);
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(1);
}
}
protected storeInstance()
}

28
uk/org/mafoo/wordsearch/f Executable file
View File

@ -0,0 +1,28 @@
Letter Frequency
E 12.02
T 9.10
A 8.12
O 7.68
I 7.31
N 6.95
S 6.28
R 6.02
H 5.92
D 4.32
L 3.98
U 2.88
C 2.71
M 2.61
F 2.30
Y 2.11
W 2.09
G 2.03
P 1.82
B 1.49
V 1.11
K 0.69
X 0.17
Q 0.11
J 0.10
Z 0.07

19
war/WEB-INF/jspf/footer.jspf Normal file → Executable file
View File

@ -1,3 +1,16 @@
<div id="footer"> <!-- Piwik -->
Generated at: https://bombadil.mafoo.org.uk/wordsearch/ <script type="text/javascript">
</div> var _paq = _paq || [];
// tracker methods like "setCustomDimension" should be called before "trackPageView"
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//mafoo.org.uk/piwik/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', '3']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<noscript><p><img src="//mafoo.org.uk/piwik/piwik.php?idsite=3&rec=1" style="border:0;" alt="" /></p></noscript>
<!-- End Piwik Code -->

BIN
war/WEB-INF/lib/sqlite-3.20.0.jar Executable file

Binary file not shown.

BIN
war/WEB-INF/lib/wordsearch.jar Executable file

Binary file not shown.

View File

@ -10,20 +10,4 @@
Wordsearch building app Wordsearch building app
</description> </description>
<context-param> </web-app>
<param-name>sqlite_db</param-name>
<param-value>/tmp/wordsearch.db</param-value>
</context-param>
<security-constraint>
<web-resource-collection>
<web-resource-name>dump</web-resource-name>
<url-pattern>/dump.jsp</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
</web-app>

View File

@ -3,7 +3,6 @@
<head> <head>
<title>Wordsearch Builder: About</title> <title>Wordsearch Builder: About</title>
<link rel="stylesheet" type="text/css" href="base.css" /> <link rel="stylesheet" type="text/css" href="base.css" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500&family=Roboto:wght@500&display=swap" rel="stylesheet">
</head> </head>
<body> <body>

View File

@ -1,5 +1,5 @@
body { body {
font-family: 'Roboto', sans-serif; font-family: sans-serif;
} }
.tooltip { .tooltip {
@ -14,16 +14,17 @@ table, th, td {
} }
table#grid td { table#grid td {
font-family: 'Fira Mono', monospace; font-family: monospace;
font-size: 14pt; font-size: 22px;
} }
#wrapper { #wrapper {
align-content: center; width: 80%;
margin: 0 auto 60px auto;
} }
#wordsearch { #wordsearch {
float: left; float: left;
margin-bottom: 24px;
} }
#words { #words {
@ -34,11 +35,8 @@ table#grid td {
#footer { #footer {
position:absolute; position:absolute;
bottom:0; bottom:0;
} width:100%;
height:60px; /* Height of the footer */
textarea#textarea_words {
font-family: 'Fira Mono', monospace;
font-size: 10pt;
} }
@media only print { @media only print {

View File

@ -3,21 +3,21 @@
<head> <head>
<title>Wordsearch builder</title> <title>Wordsearch builder</title>
<link rel="stylesheet" type="text/css" href="base.css" /> <link rel="stylesheet" type="text/css" href="base.css" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500&family=Roboto:wght@500&display=swap" rel="stylesheet">
</head> </head>
<%@ page import="uk.org.mafoo.wordsearch.*" %> <%@ page import="uk.org.mafoo.wordsearch.*" %>
<%@ page import="java.util.*" %> <%@ page import="java.util.*" %>
<%@ page import="org.apache.commons.lang.StringUtils" %> <%@ page import="org.apache.commons.lang.StringUtils" %>
<%@ page import="org.apache.commons.lang.StringEscapeUtils" %> <%@ page import="org.apache.commons.lang.StringEscapeUtils" %>
<%@ page import="java.sql.*" %>
<%@ page import="org.sqlite.*" %>
<%@ page errorPage="error.jsp" %> <%@ page errorPage="error.jsp" %>
<% <%
int height = Integer.parseInt(request.getParameter("height")); int height = Integer.parseInt(request.getParameter("height"));
int width = Integer.parseInt(request.getParameter("width")); int width = Integer.parseInt(request.getParameter("width"));
boolean simple = request.getParameter("simple") != null; Modes mode = Modes.NORMAL;
if(request.getParameter("mode") != null) {
if(request.getParameter("mode").equals("SIMPLE")) mode = Modes.SIMPLE;
if(request.getParameter("mode").equals("CROSSWORD")) mode = Modes.CROSSWORD;
}
String name = StringEscapeUtils.escapeHtml(request.getParameter("name")); String name = StringEscapeUtils.escapeHtml(request.getParameter("name"));
if (request.getParameter("words").length() > 2048) { throw new Exception("Input too large"); } if (request.getParameter("words").length() > 2048) { throw new Exception("Input too large"); }
@ -25,55 +25,25 @@
List<String> words = new ArrayList<String>(); List<String> words = new ArrayList<String>();
for ( String line : request.getParameter("words").split("\r\n")) { for ( String line : request.getParameter("words").split("\r\n")) {
words.add(line.trim().toLowerCase()); words.add(line.trim());
} }
Collections.sort(words); Collections.sort(words);
Connection conn = DriverManager.getConnection( char[][] grid = GridFactory.makeGrid(words, height, width, mode);
"jdbc:sqlite:" + getServletContext().getRealPath("/WEB-INF/files/database.sqlite"));
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO grids (remotehost, input, size_x, size_y, simple) VALUES (?, ?, ?, ?, ?)",
Statement.RETURN_GENERATED_KEYS);
// PreparedStatement getlastid = conn.prepareStatement("select last_insert_rowid();");
PreparedStatement stmt2 = conn.prepareStatement("UPDATE grids SET result=? WHERE id=?");
stmt.setString(1, request.getRemoteHost()); String csv = "";
stmt.setString(2, words.toString());
stmt.setInt(3, height);
stmt.setInt(4, width);
stmt.setBoolean(5, simple);
stmt.executeUpdate();
ResultSet record_id_rs = stmt.getGeneratedKeys();
int record_id = -1;
if(record_id_rs.next()){
record_id = record_id_rs.getInt(1);
}
// Actually generate the grid
char[][] grid = GridFactory.makeGrid(words, height, width, simple);
StringBuilder _csv = new StringBuilder();
for (char[] cs : grid) {
for(char c : cs) {
_csv.append(c);
_csv.append(",");
}
_csv.append("\r\n");
}
String csv = _csv.toString();
stmt2.setString(1, csv);
stmt2.setInt(2, record_id);
stmt2.executeUpdate();
conn.close();
%> %>
<body> <body>
<h1><%= name %></h1> <h1><%= name %></h1>
<div class="noprint"> <div class="noprint">
[ <a href="index.jsp">Start again</a> | <a id='csvdownload' href="data:text/csv;base64,<%= Base64.getEncoder().encodeToString(csv.getBytes()) %>">Download CSV</a> ] [ <a href="index.jsp">Start again</a> | <a id='csvdownload'>Download CSV</a> ]
</div> </div>
<script>
var csv = '<%= csv %>';
var csvdownload = document.getElementById('csvdownload');
csvdownload.href='data:text/csv;base64,' + btoa(csv);
</script>
</div> </div>
<div id="wrapper"> <div id="wrapper">
@ -82,18 +52,18 @@
<table id="grid"> <table id="grid">
<% for(char[] row : grid) { %> <% for(char[] row : grid) { %>
<tr> <tr>
<% for(char c : row) { <% for(char c : row) {
csv += "" + c + ','; csv += "" + c + ',';
%> %>
<td class="cell"><%= c %></td> <td class="cell"><%= c != Character.UNASSIGNED ? c : "&nbsp" %></td>
<% } %> <% } %>
</tr> </tr>
<% <%
csv += "\\n"; csv += "\\n";
} }
%> %>
</table> </table>
</div> <!-- end wordsearch --> </div> <!-- end wordsearch -->
<div id="words"> <div id="words">
<h2>Words</h2> <h2>Words</h2>
@ -103,7 +73,7 @@
<% } %> <% } %>
</ul> </ul>
</div> <!-- end words --> </div> <!-- end words -->
</div> <!-- end wrapper --> </div> <!-- end wrapper -->
<br /> <br />
<br /> <br />
<%@include file="/WEB-INF/jspf/footer.jspf" %> <%@include file="/WEB-INF/jspf/footer.jspf" %>

View File

@ -1,50 +0,0 @@
<%@ page contentType="text/html" %>
<%@ page import="java.sql.*" %>
<%@ page import="org.sqlite.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
<title>SQLite Demo</title>
</head>
<body>
<table border="1">
<thead>
<th>id</th>
<th>timestamp</th>
<th>remotehost</th>
<th>input</th>
<th>size_x</th>
<th>size_y</th>
<th>simple</th>
<th>result</th>
</thead>
<tbody>
<%
Connection conn =
DriverManager.getConnection("jdbc:sqlite:" + getServletContext().getInitParameter("sqlite_db"));
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select * from grids;");
while (rs.next()) {
out.println("<tr>");
out.println("<td>" + rs.getString("id") + "</td>");
out.println("<td>" + rs.getString("ts") + "</td>");
out.println("<td>" + rs.getString("remotehost") + "</td>");
out.println("<td><pre>" + rs.getString("input") + "</pre></td>");
out.println("<td>" + rs.getInt("size_x") + "</td>");
out.println("<td>" + rs.getInt("size_y") + "</td>");
out.println("<td>" + rs.getInt("simple") + "</td>");
out.println("<td><pre>" + rs.getString("result") + "</pre></td>");
out.println("</tr>");
}
rs.close();
conn.close();
%>
</tbody>
</table>
</body>
</html>

View File

@ -3,7 +3,6 @@
<head> <head>
<title>Wordsearch Builder</title> <title>Wordsearch Builder</title>
<link rel="stylesheet" type="text/css" href="base.css" /> <link rel="stylesheet" type="text/css" href="base.css" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500&family=Roboto:wght@500&display=swap" rel="stylesheet">
</head> </head>
<body> <body>
<h1>Wordsearch Builder</h1> <h1>Wordsearch Builder</h1>
@ -12,7 +11,7 @@
<h2>Words</h2> <h2>Words</h2>
<form action="build.jsp" method="post"> <form action="build.jsp" method="post">
Name: <input type="text" size="25" name="name" value="Wordsearch"><br /> Name: <input type="text" size="25" name="name" value="Wordsearch"><br />
<textarea id="textarea_words" name="words" rows="10"> <textarea name="words" rows="10">
Kitchen Kitchen
Lounge Lounge
Study Study
@ -26,7 +25,9 @@ Dining Room
<br /> <br />
<input type="number" name="height" min="3" max="50" value="15" /> <input type="number" name="height" min="3" max="50" value="15" />
<input type="number" name="width" min="3" max="50" value="15" /> <input type="number" name="width" min="3" max="50" value="15" />
<input type="checkbox" name="simple" value="yes">Simple [<span class="tooltip" title="In simple mode, words are only placed Left-to-Right or Top-to-Bottom">?</span>]</span> <input type="radio" name="mode" value="NORMAL" checked />Normal
<input type="radio" name="mode" value="SIMPLE" />Simple[<span class="tooltip" title="In simple mode, words are only placed Left-to-Right or Top-to-Bottom">?</span>]
<input type="radio" name="mode" value="CROSSWORD" />Crossword
<input type="submit" value="Build!" /> <input type="submit" value="Build!" />
</form> </form>

BIN
wordsearch.jar Executable file

Binary file not shown.

BIN
wordsearch.war Executable file

Binary file not shown.