-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5523dc5
Showing
14 changed files
with
689 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
target | ||
.vscode | ||
dependency-reduced-pom.xml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>nanoquiz</groupId> | ||
<artifactId>nanoquiz</artifactId> | ||
<version>24w41a</version> | ||
|
||
<properties> | ||
<maven.compiler.release>17</maven.compiler.release> | ||
<exec.mainClass>nanoquiz.Main</exec.mainClass> | ||
</properties> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-shade-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>shade</goal> | ||
</goals> | ||
<configuration> | ||
<shadedArtifactAttached>true</shadedArtifactAttached> | ||
<filters> | ||
<filter> | ||
<artifact>*:*</artifact> | ||
<excludes> | ||
<exclude>META-INF/maven/**</exclude> | ||
</excludes> | ||
</filter> | ||
</filters> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
|
||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<configuration> | ||
<archive> | ||
<manifest> | ||
<mainClass>nanoquiz.Main</mainClass> | ||
</manifest> | ||
<addMavenDescriptor>false</addMavenDescriptor> | ||
</archive> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.electronwill.night-config</groupId> | ||
<artifactId>toml</artifactId> | ||
<version>3.8.1</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.json</groupId> | ||
<artifactId>json</artifactId> | ||
<version>20240303</version> | ||
</dependency> | ||
</dependencies> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package nanoquiz; | ||
|
||
import java.awt.Color; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.net.URISyntaxException; | ||
import java.nio.file.Path; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Random; | ||
import java.util.logging.Logger; | ||
|
||
import com.electronwill.nightconfig.core.file.FileConfig; | ||
|
||
import nanoquiz.util.Timer; | ||
|
||
public abstract class Main { | ||
public static final Logger log = Logger.getLogger("nanoquiz"); | ||
static UI ui; | ||
static List<Question> questions = new ArrayList<>(); | ||
static String answer; | ||
private static final Object answerNotifier = new Object(); | ||
public static final Random random = new Random(); | ||
public static Path workdir = Path.of("."); | ||
public static FileConfig config; | ||
|
||
public static void main(String[] args) throws InterruptedException, InvocationTargetException { | ||
ui = new UI(Thread.currentThread()); | ||
ui.setText("Uruchamianie NanoQuiz...", Color.GRAY, false, true); | ||
setupFS(); | ||
loadConfig(); | ||
Updater.checkForUpdates(); | ||
QuestionLoader.loadQuestions(); | ||
if(questions.size() == 0) { | ||
log.severe(()->"NO QUESTIONS"); | ||
ui.setText("BRAK PYTAŃ", Color.RED, false, true); | ||
return; | ||
} | ||
Serialization.loadKnowledge(); | ||
try { | ||
doQuizThing(); | ||
} catch(InterruptedException e) { | ||
return; | ||
} finally { | ||
Serialization.saveKnowledge(); | ||
} | ||
} | ||
|
||
static void doQuizThing() throws InterruptedException { | ||
Question question = chooseQuestion(); | ||
while(true) { | ||
boolean good; | ||
String correctAnswer; | ||
synchronized(answerNotifier) { | ||
answer = null; | ||
} | ||
ui.setText(question.question, Color.BLACK, true, true); | ||
synchronized(answerNotifier) { | ||
while (answer == null) { | ||
answerNotifier.wait(); | ||
} | ||
good = question.answer(answer); | ||
} | ||
|
||
if (good) { | ||
ui.setText("DOBRZE!", Color.GREEN, false, false); | ||
Thread.sleep(config.<Integer>get("delay.good")); | ||
} else { | ||
ui.setText("ŹLE: " + question.answerChecker.getCorrectAnswer(), Color.RED, false, false); | ||
Thread.sleep(config.<Integer>get("delay.bad")); | ||
} | ||
if(config.<Integer>get("delay.cooldown") != 0) { | ||
ui.hide(); | ||
} | ||
Timer timer = new Timer(config.<Integer>get("delay.cooldown")); | ||
question = chooseQuestion(); | ||
timer.join(); | ||
|
||
} | ||
} | ||
|
||
static void setupFS() { | ||
try { | ||
workdir = Path.of(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent(); | ||
} catch(URISyntaxException e) {} | ||
} | ||
|
||
static void loadConfig() { | ||
config = FileConfig.builder(workdir.resolve("nq-config.toml")) | ||
.defaultResource("/nanoquiz/default-config.toml") | ||
.build(); | ||
config.load(); | ||
} | ||
|
||
static Question chooseQuestion() { | ||
Collections.shuffle(questions); | ||
Question best = null; | ||
float bestDifficulty = Float.NEGATIVE_INFINITY; | ||
int checkedAmount = (int) (questions.size()*config.<Double>get("question_selector.confidence").floatValue()); | ||
if(checkedAmount > questions.size()){ | ||
checkedAmount = questions.size(); | ||
} | ||
if(checkedAmount == 0) { | ||
checkedAmount = 1; | ||
} | ||
for(int i = 0; i < checkedAmount; i++) { | ||
Question question = questions.get(i); | ||
float difficulty = (float) (System.currentTimeMillis() - question.lastQuizzed); | ||
difficulty -= question.score * config.<Double>get("question_selector.score_factor").floatValue(); | ||
if(difficulty > bestDifficulty) { | ||
best = question; | ||
bestDifficulty = difficulty; | ||
} | ||
} | ||
return best; | ||
}; | ||
|
||
public static void handleSubmit(String answer) { | ||
synchronized(answerNotifier) { | ||
Main.answer = answer; | ||
answerNotifier.notifyAll(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package nanoquiz; | ||
|
||
import nanoquiz.checker.AnswerChecker; | ||
|
||
public class Question { | ||
public String question; | ||
AnswerChecker answerChecker; | ||
public long lastQuizzed = 0L; | ||
public float score = 0F; | ||
|
||
Question(String question, AnswerChecker answerChecker) { | ||
this.question = question; | ||
this.answerChecker = answerChecker; | ||
} | ||
|
||
public boolean answer(String answer) { | ||
lastQuizzed = System.currentTimeMillis(); | ||
float scoreDecay = Main.config.<Double>get("question_selector.score_decay").floatValue(); | ||
score *= 1-scoreDecay; | ||
if(answerChecker.check(answer)) { | ||
score += scoreDecay; | ||
return true; | ||
} | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package nanoquiz; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.File; | ||
import java.io.FileNotFoundException; | ||
import java.io.FileReader; | ||
import java.io.IOException; | ||
|
||
import nanoquiz.checker.CaseInsensitiveAnswerChecker; | ||
|
||
public abstract class QuestionLoader { | ||
static void loadQuestions() { | ||
File quizDir = Main.workdir.resolve("quiz").toFile(); | ||
quizDir.mkdir(); | ||
for (File quizFile : quizDir.listFiles()) { | ||
try { | ||
parseSimpleQuiz(quizFile); | ||
} catch(FileNotFoundException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
|
||
static void parseSimpleQuiz(File file) throws FileNotFoundException { | ||
BufferedReader reader = new BufferedReader(new FileReader(file)); | ||
try { | ||
while (true) { | ||
String question = reader.readLine(); | ||
String answer = reader.readLine(); | ||
if (question == null || answer == null) { | ||
break; | ||
} | ||
Main.questions.add(new Question(question, new CaseInsensitiveAnswerChecker(answer))); | ||
} | ||
} catch(IOException e) { | ||
e.printStackTrace(); | ||
} finally { | ||
try { | ||
reader.close(); | ||
} catch(IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package nanoquiz; | ||
|
||
import nanoquiz.util.Pair; | ||
import nanoquiz.util.IOUtil; | ||
|
||
import java.io.EOFException; | ||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.BufferedInputStream; | ||
import java.io.FileOutputStream; | ||
import java.io.BufferedOutputStream; | ||
import java.io.IOException; | ||
import java.util.HashMap; | ||
|
||
public abstract class Serialization { | ||
public static void loadKnowledge() { | ||
File knowledgeFile = Main.workdir.resolve("knowledge").toFile(); | ||
if(!knowledgeFile.exists()) return; | ||
BufferedInputStream reader = null; | ||
HashMap<Integer, Pair<Long, Float>> data = new HashMap<>(); | ||
try { | ||
reader = new BufferedInputStream(new FileInputStream(knowledgeFile)); | ||
while (true) { | ||
int id; | ||
long time; | ||
float score; | ||
try { | ||
id = IOUtil.byteArrayToInt(IOUtil.readBytesOrWait(reader, 4)); | ||
time = IOUtil.byteArrayToLong(IOUtil.readBytesOrWait(reader, 8)); | ||
score = Float.intBitsToFloat(IOUtil.byteArrayToInt(IOUtil.readBytesOrWait(reader, 4))); | ||
} catch(EOFException e) { | ||
break; | ||
} | ||
data.put(id, new Pair<Long, Float>(time, score)); | ||
} | ||
} catch(IOException e) { | ||
e.printStackTrace(); | ||
return; | ||
} finally { | ||
try { | ||
if (reader != null) { | ||
reader.close(); | ||
} | ||
} catch(IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
for(Question question : Main.questions) { | ||
Pair<Long, Float> thisData = data.get(question.question.hashCode()); | ||
if (thisData == null) { | ||
continue; | ||
} | ||
question.lastQuizzed = thisData.first(); | ||
question.score = thisData.second(); | ||
} | ||
} | ||
|
||
public static void saveKnowledge() { | ||
File knowledgeFile = Main.workdir.resolve("knowledge").toFile(); | ||
BufferedOutputStream writer = null; | ||
try { | ||
writer = new BufferedOutputStream(new FileOutputStream(knowledgeFile)); | ||
for (Question question : Main.questions) { | ||
writer.write(IOUtil.intToByteArray(question.question.hashCode())); | ||
writer.write(IOUtil.longToByteArray(question.lastQuizzed)); | ||
writer.write(IOUtil.intToByteArray(Float.floatToIntBits(question.score))); | ||
} | ||
} catch(IOException e) { | ||
e.printStackTrace(); | ||
} finally { | ||
try { | ||
if(writer != null) { | ||
writer.close(); | ||
} | ||
} catch(IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.