package com.github.donkirkby.vograbulary.ultraghost; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.github.donkirkby.vograbulary.Scheduler; import com.github.donkirkby.vograbulary.VograbularyPreferences; import com.github.donkirkby.vograbulary.ultraghost.Student.StudentListener; public class Controller implements StudentListener { //stopJesting public static final int SCORE_MILLISECONDS = 100; private static final int SEARCH_MILLISECONDS = 10; private static final int MATCH_SCORE = 300; //resumeJesting private UltraghostRandom random = new UltraghostRandom(); private VograbularyPreferences preferences; private UltraghostScreen screen; private WordList wordList = new WordList(); private Runnable scoreTask; private Runnable searchTask; private Scheduler scheduler; private List<Student> students = new ArrayList<Student>(); public void setRandom(UltraghostRandom random) { this.random = random; random.loadWordList(wordList); } public void setPreferences(VograbularyPreferences preferences) { this.preferences = preferences; } public VograbularyPreferences getPreferences() { return preferences; } public void setScreen(UltraghostScreen screen) { this.screen = screen; } public void addStudent(Student student) { students.add(student); student.setListener(this); student.setWordList(wordList); screen.setMatch(null); } public void clearStudents() { students.clear(); screen.setMatch(null); screen.focusNextButton(); } /** * Read a list of words from a reader. * @param reader contains the list of words, one per line. The reader will * be closed before the method returns. */ public void setWordList(WordList wordList) { this.wordList = wordList; random.loadWordList(wordList); for (Student student : students) { student.setWordList(wordList); } } public void setScheduler(Scheduler scheduler) { this.scheduler = scheduler; } private class ScoreTask implements Runnable { @Override public void run() { screen.getMatch().getPuzzle().adjustScore(SCORE_MILLISECONDS / 1000f); screen.refreshScore(); } } private class SearchTask implements Runnable { private List<Student> searchingStudents = new ArrayList<Student>(students); private Scheduler scheduler; public SearchTask(Scheduler scheduler) { this.scheduler = scheduler; } @Override public void run() { Iterator<Student> itr = searchingStudents.iterator(); while(itr.hasNext()) { Student student = itr.next(); boolean isStudentFinished = student.runSearchBatch(); if (isStudentFinished) { itr.remove(); } } if (searchingStudents.size() == 0) { scheduler.cancel(this); } } } @Override public void askForSolution() { screen.focusSolution(); } @Override public void showThinking() { screen.showThinking(); } @Override public void askForResponse() { screen.focusResponse(); } public void start() { getMatch().createPuzzle(wordList); restart(); } public void restart() { Puzzle puzzle = getMatch().getPuzzle(); watchPuzzle(puzzle); screen.refreshPuzzle(); for (Student student : students) { student.startSolving(puzzle); } if (scoreTask == null) { scoreTask = new ScoreTask(); scheduler.scheduleRepeating(scoreTask, SCORE_MILLISECONDS); searchTask = new SearchTask(scheduler); scheduler.scheduleRepeating(searchTask, SEARCH_MILLISECONDS); } } /** * Tell the controller to watch for changes in the current puzzle. */ public void watchPuzzle(final Puzzle puzzle) { puzzle.addListener(new Puzzle.Listener() { @Override public void completed() { Puzzle puzzle = getMatch().getPuzzle(); scheduler.cancel(scoreTask); scoreTask = null; scheduler.cancel(searchTask); searchTask = null; puzzle.getOwner().addScore(puzzle.getScore()); String hint = puzzle.findNextBetter(); puzzle.setHint(hint == null ? "Perfect!" : "hint: " + hint); screen.focusNextButton(); } @Override public void changed() { screen.refreshPuzzle(); if (puzzle.getResponse() != null && ! puzzle.isCompleted()) { screen.focusResponse(); } } }); } public Match getMatch() { Match match = screen.getMatch(); if (match == null) { match = new Match( MATCH_SCORE, students.toArray(new Student[students.size()])); match.setRandom(random); match.setMinimumWordLength( preferences.getUltraghostMinimumWordLength()); screen.setMatch(match); for (Student student : students) { student.setMatch(match); } } return match; } public void solve() { Puzzle puzzle = getMatch().getPuzzle(); if (puzzle.isCompleted()) { return; } if ( ! puzzle.getResult().isValidSolution()) { screen.focusSolution(); } else { for (Student student : students) { if (student != puzzle.getOwner()) { student.prepareResponse(); } } scheduler.cancel(searchTask); } screen.refreshPuzzle(); } public void cancelMatch() { scheduler.cancel(searchTask); } }