@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
@ -0,0 +1,20 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact type="jar" name="MathQuizApp:jar">
|
||||
<output-path>$PROJECT_DIR$/out/artifacts/MathQuizApp_jar</output-path>
|
||||
<root id="archive" name="MathQuizApp.jar">
|
||||
<element id="directory" name="META-INF">
|
||||
<element id="file-copy" path="$PROJECT_DIR$/META-INF/MANIFEST.MF" />
|
||||
</element>
|
||||
<element id="module-output" name="MathQuizApp" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/gson/gson/2.10.1/gson-2.10.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21.0.2/javafx-base-21.0.2-win.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.2/javafx-fxml-21.0.2-win.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21.0.2/javafx-graphics-21.0.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.2/javafx-controls-21.0.2-win.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21.0.2/javafx-base-21.0.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.2/javafx-controls-21.0.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.2/javafx-fxml-21.0.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21.0.2/javafx-graphics-21.0.2-win.jar" path-in-jar="/" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,216 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ArtifactsWorkspaceSettings">
|
||||
<artifacts-to-build>
|
||||
<artifact name="MathQuizApp:jar" />
|
||||
</artifacts-to-build>
|
||||
</component>
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="ad9e49ad-e421-455c-8a89-0f35a7a15146" name="Changes" comment="发行版1.03">
|
||||
<change afterPath="$PROJECT_DIR$/doc/测试文档/发行版1.04测试.md" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/com/pair/util/AsyncRegistrationHelper.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/doc/测试文档/发行版1.03测试.md" beforeDir="false" afterPath="$PROJECT_DIR$/doc/测试文档/发行版1.03测试.md" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/pom.xml" beforeDir="false" afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/com/pair/model/QuizResult.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/pair/model/QuizResult.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/com/pair/service/UserService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/pair/service/UserService.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/com/pair/ui/InfGenPage.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/pair/ui/InfGenPage.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/com/pair/ui/MainWindow.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/pair/ui/MainWindow.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/com/pair/ui/NavigablePanel.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/pair/ui/NavigablePanel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/com/pair/util/PasswordValidator.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/pair/util/PasswordValidator.java" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="Kotlin Class" />
|
||||
<option value="JavaFXApplication" />
|
||||
<option value="Interface" />
|
||||
<option value="Class" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
||||
<map>
|
||||
<entry key="$PROJECT_DIR$" value="WuBaiXuan_Branch" />
|
||||
</map>
|
||||
</option>
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="KubernetesApiPersistence">{}</component>
|
||||
<component name="KubernetesApiProvider">{
|
||||
"isMigrated": true
|
||||
}</component>
|
||||
<component name="ProblemsViewState">
|
||||
<option name="selectedTabId" value="CurrentFile" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"customColor": "",
|
||||
"associatedIndex": 1
|
||||
}</component>
|
||||
<component name="ProjectId" id="33aD4Tx1DVbp880Km6dEp5mEUbo" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"Application.Test.executor": "Run",
|
||||
"Application.TestMain.executor": "Run",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"git-widget-placeholder": "LiangJunYaoBranch",
|
||||
"kotlin-language-version-configured": "true",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"project.structure.last.edited": "Artifacts",
|
||||
"project.structure.proportion": "0.0",
|
||||
"project.structure.side.proportion": "0.0",
|
||||
"settings.editor.selected.configurable": "MavenSettings",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="C:\Users\28032\OneDrive\Desktop\PAIR\.idea" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunManager" selected="Application.Test">
|
||||
<configuration name="Test" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
|
||||
<option name="MAIN_CLASS_NAME" value="com.pair.Test" />
|
||||
<module name="MathQuizApp" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="com.pair.*" />
|
||||
<option name="ENABLED" value="true" />
|
||||
</pattern>
|
||||
</extension>
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration name="TestMain" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
|
||||
<option name="MAIN_CLASS_NAME" value="TestMain" />
|
||||
<module name="MathQuizApp" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
<set>
|
||||
<option value="bundled-jdk-9823dce3aa75-28b599e66164-intellij.indexing.shared.core-IU-242.23726.103" />
|
||||
<option value="bundled-js-predefined-d6986cc7102b-5c90d61e3bab-JavaScript-IU-242.23726.103" />
|
||||
</set>
|
||||
</attachedChunks>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="ad9e49ad-e421-455c-8a89-0f35a7a15146" name="Changes" comment="" />
|
||||
<created>1759546098925</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1759546098925</updated>
|
||||
<workItem from="1759546100740" duration="23850000" />
|
||||
<workItem from="1759587998528" duration="511000" />
|
||||
<workItem from="1759588522412" duration="122000" />
|
||||
<workItem from="1759644297457" duration="32827000" />
|
||||
<workItem from="1759720493898" duration="12215000" />
|
||||
<workItem from="1759745765663" duration="4945000" />
|
||||
<workItem from="1759752200157" duration="6627000" />
|
||||
<workItem from="1759758921108" duration="6306000" />
|
||||
<workItem from="1759815278314" duration="2288000" />
|
||||
<workItem from="1759817587775" duration="661000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="ui design v1">
|
||||
<option name="closed" value="true" />
|
||||
<created>1759588559366</created>
|
||||
<option name="number" value="00001" />
|
||||
<option name="presentableId" value="LOCAL-00001" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1759588559366</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00002" summary="partial ui implication">
|
||||
<option name="closed" value="true" />
|
||||
<created>1759684484435</created>
|
||||
<option name="number" value="00002" />
|
||||
<option name="presentableId" value="LOCAL-00002" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1759684484435</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00003" summary="version one ,do not package">
|
||||
<option name="closed" value="true" />
|
||||
<created>1759749578708</created>
|
||||
<option name="number" value="00003" />
|
||||
<option name="presentableId" value="LOCAL-00003" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1759749578708</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00004" summary="发行版1.01">
|
||||
<option name="closed" value="true" />
|
||||
<created>1759758970278</created>
|
||||
<option name="number" value="00004" />
|
||||
<option name="presentableId" value="LOCAL-00004" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1759758970278</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00005" summary="发行版1.03">
|
||||
<option name="closed" value="true" />
|
||||
<created>1759820089275</created>
|
||||
<option name="number" value="00005" />
|
||||
<option name="presentableId" value="LOCAL-00005" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1759820089275</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="6" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
<option name="TAB_STATES">
|
||||
<map>
|
||||
<entry key="MAIN">
|
||||
<value>
|
||||
<State>
|
||||
<option name="FILTERS">
|
||||
<map>
|
||||
<entry key="branch">
|
||||
<value>
|
||||
<list>
|
||||
<option value="LiangJunYaoBranch" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</State>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<MESSAGE value="ui design v1" />
|
||||
<MESSAGE value="partial ui implication" />
|
||||
<MESSAGE value="version one ,do not package" />
|
||||
<MESSAGE value="发行版1.01" />
|
||||
<MESSAGE value="发行版1.03" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="发行版1.03" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: com.pair.Test
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
# 注册码记录文件
|
||||
# 格式: 邮箱|注册码|过期时间戳|过期时间
|
||||
|
||||
test002@example.com|4R8uZYiQ|1759552847711|2025-10-04 12:40:47
|
||||
@ -0,0 +1,102 @@
|
||||
<?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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.mathquiz</groupId>
|
||||
<artifactId>MathQuizApp</artifactId>
|
||||
<name>Math Quiz Application</name>
|
||||
<version>1.04</version>
|
||||
<description>小初高数学学习软件- JavaFX版本</description>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-dependencies</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/dependencies</outputDirectory>
|
||||
<overWriteReleases>false</overWriteReleases>
|
||||
<overWriteSnapshots>false</overWriteSnapshots>
|
||||
<overWriteIfNewer>true</overWriteIfNewer>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer>
|
||||
<mainClass>com.pair.Test</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
<finalName>MathQuizApp</finalName>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<mainClass>com.pair.Test</mainClass>
|
||||
<arguments>
|
||||
<argument>--add-modules</argument>
|
||||
<argument>javafx.controls,javafx.fxml,javafx.graphics,javafx.base</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<properties>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<javafx.version>21.0.2</javafx.version>
|
||||
</properties>
|
||||
</project>
|
||||
@ -0,0 +1,7 @@
|
||||
# 发行版1.04测试
|
||||
|
||||
## 新增功能
|
||||
- 修复登录只能用用户名登录的bug
|
||||
- 新增初中高中题型
|
||||
- 新增生成注册码冷却时间60s
|
||||
- 优化动作提示
|
||||
@ -0,0 +1,38 @@
|
||||
package com.pair;// src/main/java/com/pair/Test.java
|
||||
|
||||
|
||||
import com.pair.ui.MainWindow;
|
||||
import javafx.application.Application;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Test extends Application {
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) {
|
||||
try {
|
||||
System.out.println("✅ 正在初始化 MainWindow...");
|
||||
MainWindow mainWindow = new MainWindow(primaryStage);
|
||||
Scene scene = new Scene(mainWindow, 1366, 786);
|
||||
primaryStage.setTitle("中小学数学答题系统");
|
||||
primaryStage.setScene(scene);
|
||||
primaryStage.setResizable(true);
|
||||
primaryStage.show();
|
||||
System.out.println("✅ 应用启动成功!");
|
||||
} catch (Throwable e) { // 捕获所有错误,包括 NoClassDefFoundError
|
||||
System.err.println("❌ 启动失败,异常信息:");
|
||||
e.printStackTrace();
|
||||
// 暂停 15 秒,防止窗口关闭
|
||||
try {
|
||||
Thread.sleep(15000);
|
||||
} catch (InterruptedException ignored) {}
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package com.pair.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
//选择题
|
||||
public class ChoiceQuestion {
|
||||
|
||||
private String questionText; // 题目文本
|
||||
private Object correctAnswer; // 正确答案
|
||||
private List<?> options; // 选项列表
|
||||
private Grade grade; // 所属学段
|
||||
|
||||
|
||||
|
||||
public ChoiceQuestion(String questionText, double correctAnswer,
|
||||
List<Double> options, Grade grade) {
|
||||
this.questionText = questionText;
|
||||
this.correctAnswer = correctAnswer;
|
||||
this.options = options;
|
||||
this.grade = grade;
|
||||
}
|
||||
|
||||
public ChoiceQuestion(String questionText, String correctAnswer,
|
||||
List<String> options, Grade grade) {
|
||||
this.questionText = questionText;
|
||||
this.correctAnswer = correctAnswer;
|
||||
this.options = options;
|
||||
this.grade = grade;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getQuestionText() {
|
||||
return questionText;
|
||||
}
|
||||
|
||||
public void setQuestionText(String questionText) {
|
||||
this.questionText = questionText;
|
||||
}
|
||||
|
||||
public Object getCorrectAnswer() {
|
||||
return correctAnswer;
|
||||
}
|
||||
|
||||
public void setCorrectAnswer(Object correctAnswer) {
|
||||
this.correctAnswer = correctAnswer;
|
||||
}
|
||||
|
||||
public List<?> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(List<?> options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public Grade getGrade() {
|
||||
return grade;
|
||||
}
|
||||
|
||||
public void setGrade(Grade grade) {
|
||||
this.grade = grade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChoiceQuestion{" +
|
||||
"questionText='" + questionText + '\'' +
|
||||
", correctAnswer=" + correctAnswer +
|
||||
", options=" + options +
|
||||
", grade=" + grade +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.pair.model;
|
||||
|
||||
|
||||
public enum Grade {
|
||||
// 枚举常量,初始化时传入对应的中文描述
|
||||
ELEMENTARY("小学"),
|
||||
MIDDLE("初中"),
|
||||
HIGH("高中");
|
||||
|
||||
private final String chineseName;
|
||||
|
||||
Grade(String chineseName) {
|
||||
this.chineseName = chineseName;
|
||||
}
|
||||
|
||||
public String getChineseName() {
|
||||
return chineseName;
|
||||
}
|
||||
|
||||
public static Grade valueOfChinese(String chineseName) {
|
||||
// 遍历所有枚举常量,匹配中文描述
|
||||
for (Grade grade : Grade.values()) {
|
||||
if (grade.chineseName.equals(chineseName)) {
|
||||
return grade;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("不存在对应的年级:" + chineseName);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package com.pair.model;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
//答题历史记录模型
|
||||
public class QuizHistory {
|
||||
|
||||
private String username; // 用户名
|
||||
private Date timestamp; // 答题时间
|
||||
private List<ChoiceQuestion> questions; // 题目列表
|
||||
private List<Integer> userAnswers; // 用户答案列表
|
||||
private int score; // 得分
|
||||
|
||||
|
||||
public QuizHistory(String username, Date timestamp,
|
||||
List<ChoiceQuestion> questions,
|
||||
List<Integer> userAnswers,
|
||||
int score) {
|
||||
this.username = username;
|
||||
this.timestamp = timestamp;
|
||||
this.questions = questions;
|
||||
this.userAnswers = userAnswers;
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(Date timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public List<ChoiceQuestion> getQuestions() {
|
||||
return questions;
|
||||
}
|
||||
|
||||
public void setQuestions(List<ChoiceQuestion> questions) {
|
||||
this.questions = questions;
|
||||
}
|
||||
|
||||
public List<Integer> getUserAnswers() {
|
||||
return userAnswers;
|
||||
}
|
||||
|
||||
public void setUserAnswers(List<Integer> userAnswers) {
|
||||
this.userAnswers = userAnswers;
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void setScore(int score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QuizHistory{" +
|
||||
"username='" + username + '\'' +
|
||||
", timestamp=" + timestamp +
|
||||
", questions=" + (questions != null ? questions.size() : 0) +
|
||||
", score=" + score +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.pair.model;
|
||||
|
||||
|
||||
//答题结果
|
||||
public class QuizResult {
|
||||
|
||||
private int totalQuestions; // 总题数
|
||||
private int correctCount; // 正确题数
|
||||
private int wrongCount; // 错误题数
|
||||
private int score; // 得分
|
||||
|
||||
|
||||
public QuizResult(int totalQuestions, int correctCount, int wrongCount, int score) {
|
||||
this.totalQuestions = totalQuestions;
|
||||
this.correctCount = correctCount;
|
||||
this.wrongCount = wrongCount;
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
|
||||
public int getTotalQuestions() {
|
||||
return totalQuestions;
|
||||
}
|
||||
|
||||
public void setTotalQuestions(int totalQuestions) {
|
||||
this.totalQuestions = totalQuestions;
|
||||
}
|
||||
|
||||
public int getCorrectCount() {
|
||||
return correctCount;
|
||||
}
|
||||
|
||||
public void setCorrectCount(int correctCount) {
|
||||
this.correctCount = correctCount;
|
||||
}
|
||||
|
||||
public int getWrongCount() {
|
||||
return wrongCount;
|
||||
}
|
||||
|
||||
public void setWrongCount(int wrongCount) {
|
||||
this.wrongCount = wrongCount;
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void setScore(int score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
int correctPercent = (int) ((double) correctCount / totalQuestions * 100);
|
||||
return "您答对了" + correctCount + "/" + totalQuestions + "题,得分:" + correctPercent;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,213 @@
|
||||
package com.pair.service;
|
||||
|
||||
|
||||
import com.pair.model.*;
|
||||
import com.pair.util.AppDataDirectory;
|
||||
import com.pair.util.FileUtils;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 文件IO服务
|
||||
* 负责所有数据的读写操作
|
||||
*/
|
||||
public class FileIOService {
|
||||
|
||||
private static final String DATA_DIR = AppDataDirectory.getFullPath("data");
|
||||
private static final String USERS_DIR = AppDataDirectory.getFullPath("data/users");
|
||||
private static final String HISTORY_DIR = AppDataDirectory.getFullPath("data/history");
|
||||
|
||||
private static final String REGISTRATION_CODES_FILE = AppDataDirectory.getFullPath("data/registration_codes.json");
|
||||
private static final String USERS_FILE = AppDataDirectory.getFullPath("data/users.json");
|
||||
private static final String CURRENT_USER_FILE = AppDataDirectory.getFullPath("data/current_user.json");
|
||||
|
||||
private static final Gson gson = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.setDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||
.create();
|
||||
|
||||
// ==================== 初始化 ====================
|
||||
|
||||
public FileIOService() throws IOException {
|
||||
initDataDirectory();
|
||||
}
|
||||
|
||||
public void initDataDirectory() throws IOException {
|
||||
FileUtils.createDirectoryIfNotExists(DATA_DIR);
|
||||
FileUtils.createDirectoryIfNotExists(USERS_DIR);
|
||||
FileUtils.createDirectoryIfNotExists(HISTORY_DIR);
|
||||
FileUtils.ensureFileExists(REGISTRATION_CODES_FILE);
|
||||
|
||||
if (!FileUtils.exists(USERS_FILE)) {
|
||||
Map<String, List<User>> data = new HashMap<>();
|
||||
data.put("users", new ArrayList<>());
|
||||
FileUtils.saveAsJson(data, USERS_FILE);
|
||||
}
|
||||
|
||||
System.out.println("✓ 数据目录初始化完成");
|
||||
}
|
||||
|
||||
// ==================== 用户操作 ====================
|
||||
|
||||
public void saveUser(User user) throws IOException {
|
||||
Type type = new TypeToken<Map<String, List<User>>>(){}.getType();
|
||||
Map<String, List<User>> data = FileUtils.readJsonToObject(USERS_FILE, type);
|
||||
|
||||
List<User> users = data.get("users");
|
||||
|
||||
boolean found = false;
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
if (users.get(i).getUserId().equals(user.getUserId())) {
|
||||
users.set(i, user);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
users.add(user);
|
||||
}
|
||||
|
||||
FileUtils.saveAsJson(data, USERS_FILE);
|
||||
}
|
||||
|
||||
public List<User> loadAllUsers() throws IOException {
|
||||
if (!FileUtils.exists(USERS_FILE)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Type type = new TypeToken<Map<String, List<User>>>(){}.getType();
|
||||
Map<String, List<User>> data = FileUtils.readJsonToObject(USERS_FILE, type);
|
||||
|
||||
return data.get("users");
|
||||
}
|
||||
|
||||
public User findUserByUsername(String username) throws IOException {
|
||||
List<User> users = loadAllUsers();
|
||||
|
||||
for (User user : users) {
|
||||
if (user.getUsername().equals(username)) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public User findUserByEmail(String email) throws IOException {
|
||||
List<User> users = loadAllUsers();
|
||||
|
||||
for (User user : users) {
|
||||
if (user.getEmail().equals(email)) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isUsernameExists(String username) throws IOException {
|
||||
return findUserByUsername(username) != null;
|
||||
}
|
||||
|
||||
public boolean isEmailExists(String email) throws IOException {
|
||||
return findUserByEmail(email) != null;
|
||||
}
|
||||
|
||||
public void saveCurrentUser(User user) throws IOException {
|
||||
FileUtils.saveAsJson(user, CURRENT_USER_FILE);
|
||||
}
|
||||
|
||||
public User loadCurrentUser() throws IOException {
|
||||
if (!FileUtils.exists(CURRENT_USER_FILE)) {
|
||||
return null;
|
||||
}
|
||||
return FileUtils.readJsonToObject(CURRENT_USER_FILE, User.class);
|
||||
}
|
||||
|
||||
public void clearCurrentUser() {
|
||||
FileUtils.deleteFile(CURRENT_USER_FILE);
|
||||
}
|
||||
|
||||
|
||||
public List<String> getHistoryQuestions() throws IOException {
|
||||
List<String> historyQuestions = new ArrayList<>();
|
||||
File[] files = FileUtils.listFiles(HISTORY_DIR);
|
||||
|
||||
Arrays.sort(files, (f1, f2) -> Long.compare(f2.lastModified(), f1.lastModified()));
|
||||
|
||||
int count = 0;
|
||||
for (File file : files) {
|
||||
if (count++ >= 20) break;
|
||||
|
||||
try {
|
||||
String content = FileUtils.readFileToString(file.getAbsolutePath());
|
||||
String[] lines = content.split("\n");
|
||||
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
if (lines[i].startsWith("【题目")) {
|
||||
if (i + 1 < lines.length) {
|
||||
String questionText = lines[i + 1].trim();
|
||||
if (!questionText.isEmpty()) {
|
||||
historyQuestions.add(questionText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取历史文件失败: " + file.getName());
|
||||
}
|
||||
}
|
||||
|
||||
return historyQuestions;
|
||||
}
|
||||
|
||||
// ==================== 业务逻辑方法(从 Model 移过来)====================
|
||||
|
||||
/**
|
||||
* 计算答题历史的正确数
|
||||
*/
|
||||
private int calculateCorrectCount(QuizHistory history) {
|
||||
int count = 0;
|
||||
List<ChoiceQuestion> questions = history.getQuestions();
|
||||
List<Integer> userAnswers = history.getUserAnswers();
|
||||
|
||||
for (int i = 0; i < questions.size(); i++) {
|
||||
ChoiceQuestion question = questions.get(i);
|
||||
Integer userAnswer = userAnswers.get(i);
|
||||
|
||||
if (userAnswer != null && userAnswer == getCorrectAnswerIndex(question)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取题目的正确答案索引
|
||||
*/
|
||||
private int getCorrectAnswerIndex(ChoiceQuestion question) {
|
||||
return question.getOptions().indexOf(question.getCorrectAnswer());
|
||||
}
|
||||
|
||||
// ==================== 工具方法 ====================
|
||||
|
||||
private String sanitizeFilename(String filename) {
|
||||
if (filename == null) {
|
||||
return "unknown";
|
||||
}
|
||||
return filename.replaceAll("[\\\\/:*?\"<>|]", "_");
|
||||
}
|
||||
|
||||
public String getRegistrationCodesFilePath() {
|
||||
return REGISTRATION_CODES_FILE;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.pair.service.question_generator.factory;
|
||||
|
||||
import com.pair.model.ChoiceQuestion;
|
||||
import com.pair.model.Grade;
|
||||
import com.pair.service.question_generator.strategy.elementary.*;
|
||||
import com.pair.util.RandomUtils;
|
||||
import com.pair.service.question_generator.strategy.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 小学题目工厂
|
||||
*/
|
||||
public class ElementaryQuestionFactory implements QuestionFactory {
|
||||
|
||||
private final List<QuestionStrategy> strategies;
|
||||
|
||||
public ElementaryQuestionFactory() {
|
||||
strategies = new ArrayList<>();
|
||||
// 注册所有小学题目生成策略
|
||||
strategies.add(new AdditionStrategy());
|
||||
strategies.add(new SubtractionStrategy());
|
||||
strategies.add(new MultiplicationStrategy());
|
||||
strategies.add(new DivisionStrategy());
|
||||
strategies.add(new ParenthesesAddStrategy());
|
||||
strategies.add(new ParenthesesMultiplyStrategy());
|
||||
}
|
||||
|
||||
//重载接口方法
|
||||
@Override
|
||||
public ChoiceQuestion createQuestion() {
|
||||
// 从六个题型list中随机选择一个生成题目
|
||||
QuestionStrategy strategy = RandomUtils.randomChoice(strategies);
|
||||
return strategy.generate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Grade getSupportedGrade() {
|
||||
return Grade.ELEMENTARY;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.pair.service.question_generator.factory;
|
||||
|
||||
import com.pair.model.ChoiceQuestion;
|
||||
import com.pair.model.Grade;
|
||||
import com.pair.service.question_generator.strategy.QuestionStrategy;
|
||||
import com.pair.service.question_generator.strategy.high.*;
|
||||
import com.pair.util.RandomUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 高中题目工厂
|
||||
*/
|
||||
public class HighQuestionFactory implements QuestionFactory {
|
||||
|
||||
private final List<QuestionStrategy> strategies;
|
||||
|
||||
public HighQuestionFactory() {
|
||||
strategies = new ArrayList<>();
|
||||
// 注册所有高中题目生成策略
|
||||
strategies.add(new SinStrategy());
|
||||
strategies.add(new CosStrategy());
|
||||
strategies.add(new TanStrategy());
|
||||
strategies.add(new TrigIdentityStrategy());
|
||||
strategies.add(new DerivativeStrategy());
|
||||
strategies.add(new ArithmeticSequenceSumStrategy());
|
||||
strategies.add(new LogarithmStrategy());
|
||||
strategies.add(new ProbabilityStrategy());
|
||||
strategies.add(new FunctionExtremeStrategy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChoiceQuestion createQuestion() {
|
||||
QuestionStrategy strategy = RandomUtils.randomChoice(strategies);
|
||||
return strategy.generate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Grade getSupportedGrade() {
|
||||
return Grade.HIGH;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.pair.service.question_generator.factory;
|
||||
|
||||
|
||||
|
||||
import com.pair.model.ChoiceQuestion;
|
||||
import com.pair.model.Grade;
|
||||
import com.pair.service.question_generator.strategy.elementary.ParenthesesAddStrategy;
|
||||
import com.pair.service.question_generator.strategy.elementary.ParenthesesMultiplyStrategy;
|
||||
import com.pair.service.question_generator.strategy.middle.*;
|
||||
import com.pair.util.RandomUtils;
|
||||
import com.pair.service.question_generator.strategy.QuestionStrategy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 初中题目工厂
|
||||
*/
|
||||
public class MiddleQuestionFactory implements QuestionFactory {
|
||||
|
||||
private final List<QuestionStrategy> strategies;
|
||||
|
||||
public MiddleQuestionFactory() {
|
||||
strategies = new ArrayList<>();
|
||||
// 注册所有初中题目生成策略
|
||||
strategies.add(new SquareStrategy());
|
||||
strategies.add(new SquareAddStrategy());
|
||||
strategies.add(new SqrtStrategy());
|
||||
strategies.add(new SqrtAddStrategy());
|
||||
strategies.add(new MixedSquareSqrtStrategy());
|
||||
strategies.add(new ParenthesesAddStrategy());
|
||||
strategies.add(new ParenthesesMultiplyStrategy());
|
||||
strategies.add(new LinearEquationStrategy());
|
||||
strategies.add(new QuadraticEquationStrategy());
|
||||
strategies.add(new TriangleAreaStrategy());
|
||||
strategies.add(new CircleAreaStrategy());
|
||||
strategies.add(new LinearFunctionStrategy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChoiceQuestion createQuestion() {
|
||||
QuestionStrategy strategy = RandomUtils.randomChoice(strategies);
|
||||
return strategy.generate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Grade getSupportedGrade() {
|
||||
return Grade.MIDDLE;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.pair.service.question_generator.factory;
|
||||
|
||||
import com.pair.model.ChoiceQuestion;
|
||||
import com.pair.model.Grade;
|
||||
|
||||
|
||||
/**
|
||||
* 题目工厂接口
|
||||
*/
|
||||
public interface QuestionFactory {
|
||||
|
||||
//创建题目
|
||||
ChoiceQuestion createQuestion();
|
||||
|
||||
//获取工厂支持的学段
|
||||
Grade getSupportedGrade();
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.pair.service.question_generator.strategy;
|
||||
import com.pair.model.ChoiceQuestion;
|
||||
|
||||
//题目生成题型接口
|
||||
public interface QuestionStrategy {
|
||||
|
||||
//生成题目
|
||||
ChoiceQuestion generate();
|
||||
|
||||
//题型
|
||||
String getStrategyName();
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.pair.service.question_generator.strategy.elementary;
|
||||
|
||||
import com.pair.model.ChoiceQuestion;
|
||||
import com.pair.model.Grade;
|
||||
|
||||
import com.pair.service.question_generator.strategy.AbstractQuestionStrategy;
|
||||
import com.pair.util.RandomUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加法策略
|
||||
*/
|
||||
public class AdditionStrategy extends AbstractQuestionStrategy {
|
||||
|
||||
public AdditionStrategy() {
|
||||
super(Grade.ELEMENTARY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChoiceQuestion generate() {
|
||||
int num1 = RandomUtils.nextInt(1, 30);
|
||||
int num2 = RandomUtils.nextInt(1, 30);
|
||||
|
||||
String questionText = num1 + " + " + num2;
|
||||
double answer = num1 + num2;
|
||||
|
||||
List<Double> options = generateNumericOptions(answer);
|
||||
|
||||
return new ChoiceQuestion(questionText, answer, options, grade);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStrategyName() {
|
||||
return "加法";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.pair.service.question_generator.strategy.elementary;
|
||||
|
||||
import com.pair.model.ChoiceQuestion;
|
||||
import com.pair.model.Grade;
|
||||
import com.pair.service.question_generator.strategy.AbstractQuestionStrategy;
|
||||
import com.pair.util.RandomUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 减法策略
|
||||
*/
|
||||
public class SubtractionStrategy extends AbstractQuestionStrategy {
|
||||
|
||||
public SubtractionStrategy() {
|
||||
super(Grade.ELEMENTARY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChoiceQuestion generate() {
|
||||
int num1 = RandomUtils.nextInt(1, 30);
|
||||
int num2 = RandomUtils.nextInt(1, 30);
|
||||
|
||||
// 确保结果为正数
|
||||
int larger = Math.max(num1, num2);
|
||||
int smaller = Math.min(num1, num2);
|
||||
|
||||
String questionText = larger + " - " + smaller;
|
||||
double answer = larger - smaller;
|
||||
|
||||
List<Double> options = generateNumericOptions(answer);
|
||||
|
||||
return new ChoiceQuestion(questionText, answer, options, grade);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStrategyName() {
|
||||
return "减法";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
// com/ui/NavigablePanel.java
|
||||
package com.pair.ui;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.text.Font;
|
||||
|
||||
public abstract class NavigablePanel extends BorderPane {
|
||||
|
||||
|
||||
public NavigablePanel(Runnable onBack) {
|
||||
Button backButton = new Button("←");
|
||||
backButton.setOnAction(e -> onBack.run());
|
||||
backButton.setPrefSize(UIConstants.BACK_BUTTON_WIDTH, UIConstants.BACK_BUTTON_HEIGHT);
|
||||
backButton.setFont(Font.font(UIConstants.FONT_FAMILY, UIConstants.BUTTON_FONT_SIZE));
|
||||
backButton.setStyle(
|
||||
"-fx-background-radius: 50; " +
|
||||
"-fx-background-color: " + UIConstants.COLOR_ACCENT + "; " +
|
||||
"-fx-text-fill: white; " +
|
||||
"-fx-font-weight: bold;"
|
||||
);
|
||||
|
||||
HBox topBar = new HBox(10);
|
||||
topBar.setPadding(UIConstants.TOP_BAR_PADDING);
|
||||
topBar.setAlignment(Pos.CENTER_LEFT);
|
||||
topBar.getChildren().add(backButton);
|
||||
|
||||
this.setTop(topBar);
|
||||
}
|
||||
|
||||
protected static void showErrorAlert(String title, String message) {
|
||||
Platform.runLater(() -> {
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setTitle(title);
|
||||
alert.setHeaderText(null);
|
||||
alert.setContentText(message);
|
||||
alert.showAndWait();
|
||||
});
|
||||
}
|
||||
|
||||
protected static void showInfoAlert(String title, String message) {
|
||||
Platform.runLater(() -> {
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle(title);
|
||||
alert.setHeaderText(null);
|
||||
alert.setContentText(message);
|
||||
alert.showAndWait();
|
||||
});
|
||||
}
|
||||
|
||||
// 子类构造函数中调用
|
||||
protected final void initializeContent() {
|
||||
buildContent();
|
||||
}
|
||||
protected abstract void buildContent();
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.pair.ui;
|
||||
|
||||
public enum Panel {
|
||||
START, // 开始页面
|
||||
LOGIN, // 登录页面
|
||||
REGISTER, // 注册页面
|
||||
INF_GEN, // 个人信息+生成题目页面
|
||||
PASSWORDMODIFY, // 修改密码页面
|
||||
QUIZ, // 答题页面
|
||||
RESULT // 得分页面
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
// com/ui/StartPage.java
|
||||
package com.pair.ui;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.FontWeight;
|
||||
|
||||
public class StartPage extends VBox {
|
||||
|
||||
private final Button startButton;
|
||||
|
||||
public StartPage(Runnable onStart) {
|
||||
this.setAlignment(Pos.CENTER);
|
||||
this.setSpacing(UIConstants.DEFAULT_SPACING);
|
||||
this.setPadding(UIConstants.DEFAULT_PADDING);
|
||||
|
||||
Label titleLabel = new Label("中小学数学答题系统");
|
||||
titleLabel.setFont(Font.font(UIConstants.FONT_FAMILY, FontWeight.BOLD, UIConstants.TITLE_FONT_SIZE));
|
||||
|
||||
Label subtitleLabel = new Label("HNU@梁峻耀 吴佰轩");
|
||||
subtitleLabel.setFont(Font.font(UIConstants.FONT_FAMILY, UIConstants.SUBTITLE_FONT_SIZE));
|
||||
subtitleLabel.setStyle("-fx-text-fill: gray;");
|
||||
|
||||
startButton = new Button("开始");
|
||||
startButton.setPrefSize(UIConstants.BUTTON_WIDTH, UIConstants.BUTTON_HEIGHT);
|
||||
startButton.setFont(Font.font(UIConstants.FONT_FAMILY, UIConstants.BUTTON_FONT_SIZE));
|
||||
startButton.setOnAction(e -> onStart.run());
|
||||
startButton.setStyle(UIConstants.BUTTON_STYLE);
|
||||
startButton.setOnMouseEntered(e -> startButton.setStyle(UIConstants.BUTTON_STYLE + UIConstants.BUTTON_HOVER_STYLE));
|
||||
startButton.setOnMouseExited(e -> startButton.setStyle(UIConstants.BUTTON_STYLE));
|
||||
|
||||
this.getChildren().addAll(titleLabel, subtitleLabel, startButton);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
// UIConstants.java
|
||||
package com.pair.ui;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
public final class UIConstants {
|
||||
private UIConstants() {}
|
||||
|
||||
public static final double LABEL_ITEM_TITLE_SIZE = 16.0;
|
||||
|
||||
// 间距与边距
|
||||
public static final double DEFAULT_SPACING = 15.0;
|
||||
public static final Insets DEFAULT_PADDING = new Insets(40);
|
||||
public static final Insets SMALL_PADDING = new Insets(20);
|
||||
public static final Insets TOP_BAR_PADDING = new Insets(10);
|
||||
|
||||
// 字体
|
||||
public static final String FONT_FAMILY = "Microsoft YaHei";
|
||||
public static final double TITLE_FONT_SIZE = 26.0;
|
||||
public static final double SUBTITLE_FONT_SIZE = 16.0;
|
||||
public static final double BUTTON_FONT_SIZE = 15.0;
|
||||
public static final double LABEL_FONT_SIZE = 14.0;
|
||||
public static final double INPUT_FONT_SIZE = 14.0;
|
||||
public static final double HINT_FONT_SIZE = 12.0;
|
||||
public static final double ERROR_FONT_SIZE = 12.0;
|
||||
public static final double QUIZ_TITLE_FONT_SIZE = 20.0;
|
||||
public static final double SCORE_FONT_SIZE = 32.0;
|
||||
|
||||
// 按钮尺寸
|
||||
public static final double BUTTON_WIDTH = 140.0;
|
||||
public static final double BUTTON_HEIGHT = 40.0;
|
||||
public static final double BACK_BUTTON_WIDTH = 80.0;
|
||||
public static final double BACK_BUTTON_HEIGHT = 30.0;
|
||||
|
||||
// 颜色
|
||||
public static final String COLOR_PRIMARY = "#2c3e50";
|
||||
public static final String COLOR_ACCENT = "#3498db";
|
||||
public static final String COLOR_ERROR = "#e74c3c";
|
||||
public static final String COLOR_HINT = "#7f8c8d";
|
||||
public static final String COLOR_BACKGROUND = "#ecf0f1";
|
||||
|
||||
// 按钮样式
|
||||
public static final String BUTTON_STYLE =
|
||||
"-fx-background-color: " + COLOR_ACCENT + "; " +
|
||||
"-fx-text-fill: white; " +
|
||||
"-fx-background-radius: 8; " +
|
||||
"-fx-font-size: " + BUTTON_FONT_SIZE + "px; " +
|
||||
"-fx-font-family: '" + FONT_FAMILY + "'; " +
|
||||
"-fx-cursor: hand;";
|
||||
|
||||
public static final String BUTTON_HOVER_STYLE =
|
||||
"-fx-background-color: #2980b9;";
|
||||
|
||||
// 输入框样式
|
||||
public static final String INPUT_STYLE =
|
||||
"-fx-background-radius: 8; " +
|
||||
"-fx-border-radius: 8; " +
|
||||
"-fx-border-color: #bdc3c7; " +
|
||||
"-fx-padding: 8; " +
|
||||
"-fx-font-size: " + INPUT_FONT_SIZE + "px; " +
|
||||
"-fx-font-family: '" + FONT_FAMILY + "';";
|
||||
|
||||
// 表单容器样式
|
||||
public static final String FORM_STYLE =
|
||||
"-fx-background-color: white; " +
|
||||
"-fx-background-radius: 12; " +
|
||||
"-fx-border-radius: 12; " +
|
||||
"-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 10, 0, 0, 5);";
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.pair.util;
|
||||
|
||||
/**
|
||||
* 应用数据目录管理器
|
||||
* 根据不同操作系统返回合适的应用数据存储路径
|
||||
*/
|
||||
public class AppDataDirectory {
|
||||
private static final String APP_NAME = "Math-Quiz-App"; // 替换为你的应用名
|
||||
|
||||
/**
|
||||
* 获取应用数据根目录
|
||||
*/
|
||||
public static String getApplicationDataDirectory() {
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
String basePath;
|
||||
|
||||
if (os.contains("win")) {
|
||||
// Windows
|
||||
String appData = System.getenv("APPDATA");
|
||||
basePath = (appData != null) ? appData : System.getProperty("user.home") + "/AppData/Roaming";
|
||||
} else if (os.contains("mac")) {
|
||||
// macOS
|
||||
basePath = System.getProperty("user.home") + "/Library/Application Support";
|
||||
} else {
|
||||
// Linux/Unix
|
||||
String xdgDataHome = System.getenv("XDG_DATA_HOME");
|
||||
if (xdgDataHome == null) {
|
||||
xdgDataHome = System.getProperty("user.home") + "/.local/share";
|
||||
}
|
||||
basePath = xdgDataHome;
|
||||
}
|
||||
|
||||
return basePath + "/" + APP_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取完整的应用数据路径
|
||||
*/
|
||||
public static String getFullPath(String relativePath) {
|
||||
String appDataDir = getApplicationDataDirectory();
|
||||
return appDataDir + "/" + relativePath;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue