parent
4199a269fd
commit
e889b75605
@ -0,0 +1,104 @@ |
||||
package me.lensferno.dogename.select; |
||||
|
||||
import javafx.animation.AnimationTimer; |
||||
import javafx.beans.property.SimpleBooleanProperty; |
||||
import javafx.beans.property.StringProperty; |
||||
import javafx.beans.value.ChangeListener; |
||||
import me.lensferno.dogename.configs.MainConfig; |
||||
import me.lensferno.dogename.configs.VoiceConfig; |
||||
import me.lensferno.dogename.data.History; |
||||
import me.lensferno.dogename.data.NameData; |
||||
import me.lensferno.dogename.select.core.Worker; |
||||
import me.lensferno.dogename.voice.TokenManager; |
||||
import me.lensferno.dogename.voice.VoicePlayer; |
||||
|
||||
public final class Selector { |
||||
|
||||
Processor processor = new Processor(); |
||||
|
||||
private VoicePlayer voicePlayer = null; |
||||
|
||||
public Selector() { |
||||
initialVoicePlayer(); |
||||
} |
||||
|
||||
public void initialVoicePlayer() { |
||||
TokenManager tokenManager = new TokenManager(); |
||||
VoiceConfig voiceConfig = new VoiceConfig(); |
||||
tokenManager.init(); |
||||
if (tokenManager.getTokenStatus() == TokenManager.TOKEN_OK) { |
||||
voicePlayer = new VoicePlayer(tokenManager.getToken(), voiceConfig); |
||||
} |
||||
} |
||||
|
||||
public void run() { |
||||
processor.setNumberRange(); |
||||
processor.updateNewValue(); |
||||
processor.stoppedIndicatorProperty().set(false); |
||||
|
||||
processor.start(); |
||||
} |
||||
|
||||
public void forceStop() { |
||||
processor.stopProcess(); |
||||
} |
||||
|
||||
public void initialVariable(MainConfig config, NameData nameData, History history, StringProperty... labelTexts) { |
||||
processor.initialVariable(config, voicePlayer, nameData, history, labelTexts); |
||||
} |
||||
|
||||
public boolean isWorkerRunning() { |
||||
return processor.isWorkerRunning(); |
||||
} |
||||
|
||||
public void addStoppedEventListener(ChangeListener<? super Boolean> listener) { |
||||
processor.stoppedIndicatorProperty().addListener(listener); |
||||
} |
||||
|
||||
// ---------------------------------------------------
|
||||
static class Processor extends AnimationTimer { |
||||
|
||||
private Worker coreWorker; |
||||
|
||||
MainConfig config = null; |
||||
|
||||
protected void initialVariable(MainConfig config, VoicePlayer voicePlayer, NameData nameData, History history, StringProperty... labelTexts) { |
||||
coreWorker = new Worker(labelTexts, config, nameData, history, voicePlayer); |
||||
this.config = config; |
||||
} |
||||
|
||||
protected void updateNewValue() { |
||||
coreWorker.setSpeed(100 - config.getSpeed()); |
||||
coreWorker.setMaxTotalCount(config.getMaxTotalCount()); |
||||
} |
||||
|
||||
protected SimpleBooleanProperty stoppedIndicatorProperty() { |
||||
return coreWorker.stoppedIndicatorProperty(); |
||||
} |
||||
|
||||
@Override |
||||
public void handle(long time) { |
||||
coreWorker.displaySelectedResult(); |
||||
if (coreWorker.getStoppedIndicator()) { |
||||
this.stop(); |
||||
} |
||||
} |
||||
|
||||
public void stopProcess() { |
||||
coreWorker.setForceStop(true); |
||||
} |
||||
|
||||
public boolean isWorkerRunning() { |
||||
return !coreWorker.getStoppedIndicator(); |
||||
} |
||||
|
||||
public void setNumberRange() { |
||||
int minNumber = Integer.parseInt(config.getMinNumber()); |
||||
int maxNumber = Integer.parseInt(config.getMaxNumber()); |
||||
coreWorker.setNumberRange(minNumber, maxNumber); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,203 @@ |
||||
package me.lensferno.dogename.select.core; |
||||
|
||||
import javafx.beans.property.SimpleBooleanProperty; |
||||
import javafx.beans.property.StringProperty; |
||||
import me.lensferno.dogename.configs.MainConfig; |
||||
import me.lensferno.dogename.data.History; |
||||
import me.lensferno.dogename.data.NameData; |
||||
|
||||
import me.lensferno.dogename.utils.Random; |
||||
import me.lensferno.dogename.voice.VoicePlayer; |
||||
|
||||
public final class Worker { |
||||
|
||||
private final Random randomNumber = new Random(); |
||||
|
||||
private final StringProperty[] labelTexts; |
||||
private final SimpleBooleanProperty stoppedIndicator = new SimpleBooleanProperty(true); |
||||
|
||||
private final MainConfig config; |
||||
|
||||
//挑选方法
|
||||
private final int selectMethod = MainConfig.METHOD_NAME; |
||||
private final NameData nameData; |
||||
|
||||
private final History history; |
||||
|
||||
private final VoicePlayer voicePlayer; |
||||
|
||||
private int speed = 0; |
||||
|
||||
//数值范围最大最小值
|
||||
private final int[] numberRange = new int[2]; |
||||
private final int MIN_NUMBER = 0; |
||||
private final int MAX_NUMBER = 1; |
||||
|
||||
//挑选次数和每一轮的挑选次数
|
||||
private int maxTotalCount = MainConfig.DEFAULT_MAX_TOTAL_COUNT; |
||||
private int maxCycleCount = 0; |
||||
|
||||
//已经挑选了多少次
|
||||
private int totalCount = 0; |
||||
private int cycleCount = 0; |
||||
|
||||
private boolean finalResult = true; |
||||
|
||||
private boolean forceStop = false; |
||||
|
||||
private String selectedResult; |
||||
private boolean continueSelecting = false; |
||||
|
||||
private int resultLabelId = 0; |
||||
|
||||
private final Counter counter = new Counter(); |
||||
|
||||
public Worker(StringProperty[] labelTexts, MainConfig config, NameData nameData, History history, VoicePlayer voicePlayer) { |
||||
this.labelTexts = labelTexts; |
||||
this.config = config; |
||||
this.nameData = nameData; |
||||
this.history = history; |
||||
this.voicePlayer = voicePlayer; |
||||
} |
||||
|
||||
private void select() { |
||||
// try的位置待定(前面or后面)
|
||||
// 延时用,用于调整挑选速度
|
||||
try { |
||||
Thread.sleep(speed); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
stoppedIndicator.set(false); |
||||
|
||||
// 若 计数已达最大总数(挑选次数)或强制停止,进入停止分支,
|
||||
if (totalCount >= maxTotalCount || forceStop) { |
||||
// 任意三种情况就停止:已忽略名单中没有该名字;不考虑忽略名单;强制停止
|
||||
// 如果不是这三种情况就选到符合其中一种情况为止
|
||||
// 由于后两者在安排进程中不可能改变,因此继续挑选后只有选中的结果不在忽略名单中才会结束挑选
|
||||
// 若忽略名单已满(名单中数量=总的名单数量),点击“安排一下”时会提示已满,无法再进行挑选,因此在运行时总有 忽略名单<总名单,总有名字不在忽略列表中,不会死循环,放心吧
|
||||
boolean resultIgnored = (config.getChooseMethod() == MainConfig.METHOD_NAME) ? (nameData.getIgnoreNameList().contains(selectedResult)) : (nameData.getIgnoreNumberList().contains(selectedResult)); |
||||
if (!resultIgnored || !config.getPassSelectedResult() || forceStop) { |
||||
this.stopSelect(); |
||||
finalResult = true; |
||||
return; |
||||
} else { |
||||
continueSelecting = true; |
||||
} |
||||
} |
||||
|
||||
counter.count(); |
||||
resultLabelId = counter.getNewResultLabelId(); |
||||
finalResult = false; |
||||
|
||||
this.selectedResult = this.pick(config.getChooseMethod()); |
||||
} |
||||
|
||||
public void stopSelect() { |
||||
if (config.getPassSelectedResult()) { |
||||
nameData.getIgnoreNameList().add(selectedResult); |
||||
} |
||||
|
||||
if (config.getEqualMode()) { |
||||
nameData.writeIgnoreList(NameData.NAME_ONLY); |
||||
} |
||||
|
||||
history.addHistory(selectedResult); |
||||
|
||||
if (config.getVoicePlay() && voicePlayer != null) { |
||||
voicePlayer.playVoice(selectedResult); |
||||
} |
||||
|
||||
counter.resetCounter(); |
||||
stoppedIndicator.set(true); |
||||
forceStop = false; |
||||
System.gc(); |
||||
} |
||||
|
||||
private String pick(int selectMethod) { |
||||
switch (selectMethod) { |
||||
case MainConfig.METHOD_NAME: |
||||
return nameData.randomGet(config.getSecureRandom()); |
||||
case MainConfig.METHOD_NUMBER: |
||||
randomNumber.setUseSecureRandom(config.getSecureRandom()); |
||||
return String.valueOf(randomNumber.getRandomNumber(numberRange[MIN_NUMBER], numberRange[MAX_NUMBER])); |
||||
default: |
||||
return "(´・ω・`)?"; |
||||
} |
||||
} |
||||
|
||||
public void displaySelectedResult() { |
||||
this.select(); |
||||
|
||||
if (!finalResult) { |
||||
labelTexts[resultLabelId].set(selectedResult); |
||||
} else { |
||||
for (StringProperty labelText : labelTexts) { |
||||
if (labelText.get().contains("→")) { |
||||
labelText.set(labelText.get().replace("→", "").replace("←", "")); |
||||
} |
||||
} |
||||
labelTexts[resultLabelId].set(String.format("→%s←", selectedResult)); |
||||
} |
||||
} |
||||
|
||||
// 这里有个内部类Counter计数菌
|
||||
final class Counter { |
||||
|
||||
private int newResultLabelId = 0; |
||||
|
||||
protected void count() { |
||||
newResultLabelId = resultLabelId; |
||||
|
||||
// 每一轮的计数到达最大时并且不强制继续这轮挑选时,重置这一轮的挑选,并指派新的显示label
|
||||
// 否则这一轮的计数直接+1
|
||||
if (cycleCount >= maxCycleCount && !continueSelecting) { |
||||
cycleCount = 0; |
||||
maxCycleCount = randomNumber.getRandomNumber(1, maxTotalCount - totalCount); |
||||
newResultLabelId = randomNumber.getRandomNumber(labelTexts.length - 1); |
||||
} else { |
||||
cycleCount++; |
||||
} |
||||
|
||||
totalCount++; |
||||
} |
||||
|
||||
protected void resetCounter() { |
||||
totalCount = 0; |
||||
cycleCount = 0; |
||||
maxCycleCount = 0; |
||||
|
||||
continueSelecting = false; |
||||
} |
||||
|
||||
protected int getNewResultLabelId() { |
||||
return newResultLabelId; |
||||
} |
||||
} |
||||
|
||||
public boolean getStoppedIndicator() { |
||||
return stoppedIndicator.get(); |
||||
} |
||||
|
||||
public SimpleBooleanProperty stoppedIndicatorProperty() { |
||||
return stoppedIndicator; |
||||
} |
||||
|
||||
public void setNumberRange(int minNumber, int maxNumber) { |
||||
this.numberRange[MIN_NUMBER] = minNumber; |
||||
this.numberRange[MAX_NUMBER] = maxNumber; |
||||
} |
||||
|
||||
public void setForceStop(boolean forceStop) { |
||||
this.forceStop = forceStop; |
||||
} |
||||
|
||||
public void setMaxTotalCount(int maxTotalCount) { |
||||
this.maxTotalCount = maxTotalCount; |
||||
} |
||||
|
||||
public void setSpeed(int speed) { |
||||
this.speed = speed; |
||||
} |
||||
} |
@ -0,0 +1,32 @@ |
||||
package me.lensferno.dogename.utils; |
||||
|
||||
import java.security.SecureRandom; |
||||
|
||||
public final class Random { |
||||
|
||||
private final java.util.Random random = new java.util.Random(); |
||||
private final java.util.Random secRandom = new SecureRandom(); |
||||
|
||||
private boolean useSecureRandom = true; |
||||
|
||||
public void setUseSecureRandom(boolean useSecureRandom) { |
||||
this.useSecureRandom = useSecureRandom; |
||||
} |
||||
|
||||
public int getRandomNumber (int minNumber, int maxNumber) { |
||||
if (useSecureRandom){ |
||||
return minNumber + secRandom.nextInt(maxNumber - minNumber + 1); |
||||
} else { |
||||
return minNumber + random.nextInt(maxNumber - minNumber + 1); |
||||
} |
||||
} |
||||
|
||||
public int getRandomNumber (int maxNumber) { |
||||
if (useSecureRandom){ |
||||
return secRandom.nextInt(maxNumber + 1); |
||||
} else { |
||||
return random.nextInt(maxNumber + 1); |
||||
} |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue