Skip to content

Commit 5e1b4fa

Browse files
committed
v1.2
1 parent 6b90960 commit 5e1b4fa

File tree

16 files changed

+276
-201
lines changed

16 files changed

+276
-201
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ tasks.withType(JavaCompile) {
1010
}
1111

1212
group 'com.github.dedinc.mindvault'
13-
version '1.1'
13+
version '1.2'
1414

1515
repositories {
1616
mavenCentral()

screenshot.png

3.29 KB
Loading

screenshot2.png

6.15 KB
Loading
Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.github.dedinc.mindvault.core;
22

3-
import java.util.Arrays;
4-
import java.util.Locale;
3+
import java.math.BigDecimal;
4+
import java.math.RoundingMode;
5+
import java.util.Collections;
6+
import java.util.List;
57

68
public class Grades {
79
public static int calculateTypeSpeed(long startTime, String text) {
@@ -10,40 +12,41 @@ public static int calculateTypeSpeed(long startTime, String text) {
1012
return Math.round(text.length() / typeTime);
1113
}
1214

13-
public static double calculateTypingTime(String text, int charsPerSecond) {
15+
public static double calculateTypingTime(String text, int charsPerSecond, Session session) {
1416
double typingTime = text.length() / (double) charsPerSecond;
15-
double thinkingTime = typingTime * 0.3;
16-
return Double.parseDouble(String.format(Locale.US, "%.2f", typingTime + thinkingTime));
17+
double thinkingTime = typingTime * 0.3 + calculateTotalGrade(session.getGrades()) >= 0.85 ? 3 : 5;
18+
return round(typingTime + thinkingTime);
1719
}
1820

1921
public static double calculateTypeGrade(double typedTime, double maxTime) {
20-
return Double.parseDouble(String.format(Locale.US, "%.2f", Math.max(Math.min(maxTime / typedTime, 1), 0)));
22+
return round(Math.max(Math.min(maxTime / typedTime, 1), 0));
2123
}
2224

2325
public static double calculateStringsRatio(String s1, String s2) {
2426
String longer = s1.length() >= s2.length() ? s1 : s2;
2527
String shorter = s1.length() < s2.length() ? s1 : s2;
2628
int longerLength = longer.length();
2729
if (longerLength == 0) return 1.0;
28-
int matchedCount = (int) shorter.chars()
29-
.filter(c -> c == longer.charAt(shorter.indexOf(c)))
30-
.count();
31-
return Double.parseDouble(String.format(Locale.US, "%.2f", (double) matchedCount / longerLength));
30+
long matchedCount = shorter.chars().filter(c -> longer.indexOf(c) != -1).count();
31+
return round((double) matchedCount / longerLength);
3232
}
3333

34-
public static double calculateTotalGrade(double[] grades) {
35-
Arrays.sort(grades);
36-
int midIndex = grades.length / 2;
34+
public static double calculateTotalGrade(List<Double> grades) {
35+
if (grades.isEmpty()) return 0.0;
36+
Collections.sort(grades);
37+
int midIndex = grades.size() / 2;
3738
double median;
38-
if (grades.length > 0) {
39-
if (grades.length % 2 == 0) {
40-
median = (grades[midIndex - 1] + grades[midIndex]) / 2.0;
41-
} else {
42-
median = grades[midIndex];
43-
}
44-
String formattedMedian = String.format(Locale.US, "%.2f", median);
45-
return Math.min(Double.parseDouble(formattedMedian), 1.0);
39+
if (grades.size() % 2 == 0) {
40+
median = (grades.get(midIndex - 1) + grades.get(midIndex)) / 2.0;
41+
} else {
42+
median = grades.get(midIndex);
4643
}
47-
return 0.0;
44+
return Math.min(round(median), 1.0);
45+
}
46+
47+
private static double round(double value) {
48+
BigDecimal bd = BigDecimal.valueOf(value);
49+
bd = bd.setScale(2, RoundingMode.HALF_UP);
50+
return bd.doubleValue();
4851
}
4952
}

src/main/java/com/github/dedinc/mindvault/core/Intervals.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ public class Intervals {
55

66
public static boolean isReviseViolated(long learnDate, long[] reviseDates) {
77
for (int i = 0; i < reviseDates.length; i++) {
8-
long currentDate = i == 0 ? learnDate : reviseDates[i - 1];
9-
long daysSinceLearning = (Time.getUnix() - learnDate) / 86400;
108
long daysSinceRevision = (reviseDates[i] - learnDate) / 86400;
11-
long daysSinceLearningToRevision = daysSinceLearning - daysSinceRevision;
129
for (int interval : intervals) {
1310
if (daysSinceRevision > Math.round(interval + interval / 3.0)) {
1411
return true;

src/main/java/com/github/dedinc/mindvault/core/Manager.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import org.json.JSONArray;
66
import org.json.JSONObject;
77
import org.json.JSONTokener;
8+
89
import java.io.FileReader;
910
import java.io.FileWriter;
1011
import java.io.IOException;
12+
import java.time.LocalDate;
1113
import java.util.ArrayList;
12-
import java.util.HashMap;
14+
import java.util.EnumMap;
1315
import java.util.List;
1416
import java.util.Map;
1517

@@ -18,6 +20,8 @@ public static void saveSession(Session session, String filename) {
1820
JSONObject json = new JSONObject();
1921
json.put("typeSpeed", session.getTypeSpeed());
2022
json.put("perSessionCards", session.getPerSessionCards());
23+
json.put("completedBlocks", session.getPomodoroTimer().getCompletedBlocks());
24+
json.put("lastTrainingDate", session.getPomodoroTimer().getLastTrainingDate().toString());
2125

2226
JSONObject cardsJson = new JSONObject();
2327
for (Map.Entry<State, List<Card>> entry : session.getCategories().entrySet()) {
@@ -48,11 +52,12 @@ public static void saveSession(Session session, String filename) {
4852
public static Session loadSession(String filename) {
4953
try (FileReader reader = new FileReader(filename)) {
5054
JSONObject json = new JSONObject(new JSONTokener(reader));
51-
5255
int typeSpeed = json.getInt("typeSpeed");
5356
int perSessionCards = json.getInt("perSessionCards");
57+
int completedBlocks = json.getInt("completedBlocks");
58+
LocalDate lastTrainingDate = LocalDate.parse(json.getString("lastTrainingDate"));
5459

55-
Map<State, List<Card>> cards = new HashMap<>();
60+
Map<State, List<Card>> cards = new EnumMap<>(State.class);
5661
JSONObject cardsJson = json.getJSONObject("cards");
5762
for (String stateStr : cardsJson.keySet()) {
5863
State state = State.valueOf(stateStr);
@@ -85,7 +90,8 @@ public static Session loadSession(String filename) {
8590
session.setCards(cards);
8691
session.setGrades(grades);
8792
session.setPerSessionCards(perSessionCards);
88-
93+
session.getPomodoroTimer().setCompletedBlocks(completedBlocks);
94+
session.getPomodoroTimer().setLastTrainingDate(lastTrainingDate);
8995
return session;
9096
} catch (IOException e) {
9197
System.out.println("Error loading session: " + e.getMessage());
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.github.dedinc.mindvault.core;
2+
3+
import java.time.LocalDate;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
7+
public class PomodoroTimer {
8+
private static final List<Integer> POMODORO_INTERVALS = Arrays.asList(20, 5, 20, 5, 20, 15);
9+
public static final int MAX_BLOCKS_PER_DAY = 3;
10+
11+
private int currentInterval;
12+
private int completedBlocks;
13+
private LocalDate lastTrainingDate;
14+
15+
public PomodoroTimer() {
16+
currentInterval = 0;
17+
completedBlocks = 0;
18+
lastTrainingDate = LocalDate.now();
19+
}
20+
21+
public int getCurrentInterval() {
22+
return POMODORO_INTERVALS.get(currentInterval);
23+
}
24+
25+
public boolean isBreakInterval() {
26+
return currentInterval % 2 != 0;
27+
}
28+
29+
public void nextInterval() {
30+
currentInterval = (currentInterval + 1) % POMODORO_INTERVALS.size();
31+
if (currentInterval == 0) {
32+
completedBlocks++;
33+
}
34+
}
35+
36+
public int getCompletedBlocks() {
37+
return completedBlocks;
38+
}
39+
40+
public LocalDate getLastTrainingDate() {
41+
return lastTrainingDate;
42+
}
43+
44+
public void setCompletedBlocks(int completedBlocks) {
45+
this.completedBlocks = completedBlocks;
46+
}
47+
48+
public void setLastTrainingDate(LocalDate lastTrainingDate) {
49+
this.lastTrainingDate = lastTrainingDate;
50+
}
51+
52+
public boolean canStartSession() {
53+
return !isBreakInterval() && completedBlocks < MAX_BLOCKS_PER_DAY;
54+
}
55+
}

src/main/java/com/github/dedinc/mindvault/core/Session.java

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,37 @@
44
import com.github.dedinc.mindvault.core.objects.State;
55

66
import java.util.*;
7+
import java.util.stream.Collectors;
78

89
public class Session {
910
private int typeSpeed;
1011
private Map<State, List<Card>> cards;
1112
private List<Double> grades;
1213
private int perSessionCards;
14+
private List<Card> allCardsCache;
15+
16+
private PomodoroTimer pomodoroTimer;
1317

1418
public Session() {
1519
this(Time.getUnix() - 1, "\n");
1620
}
1721

1822
public Session(long startTime, String text) {
1923
this.typeSpeed = Grades.calculateTypeSpeed(startTime, text);
20-
this.cards = new HashMap<>();
24+
this.cards = new EnumMap<>(State.class);
2125
for (State state : State.values()) {
2226
this.cards.put(state, new ArrayList<>());
2327
}
2428
this.grades = new ArrayList<>();
2529
this.perSessionCards = 5;
30+
this.allCardsCache = null;
31+
this.pomodoroTimer = new PomodoroTimer();
2632
}
2733

2834
public void addCard(String question, String answer) {
2935
Card newCard = new Card(question, answer, 0, new long[0]);
3036
cards.get(State.LEARN).add(newCard);
37+
invalidateAllCardsCache();
3138
}
3239

3340
public void addCards(List<Card> cards) {
@@ -40,6 +47,7 @@ public void removeCard(String question) {
4047
for (List<Card> cardList : cards.values()) {
4148
cardList.removeIf(card -> card.getQuestion().equals(question));
4249
}
50+
invalidateAllCardsCache();
4351
}
4452

4553
public void removeCards(List<String> questions) {
@@ -50,32 +58,26 @@ public void removeCards(List<String> questions) {
5058

5159
public void moveCard(Card card, State newState) {
5260
State currentState = card.getCategory(this);
53-
5461
if (currentState == newState) {
5562
return;
5663
}
57-
5864
cards.get(currentState).removeIf(c -> c.getQuestion().equals(card.getQuestion()));
5965
cards.get(newState).add(card);
66+
invalidateAllCardsCache();
6067
}
6168

6269
public void updateCards() {
63-
Map<State, List<Card>> cardsToMove = new HashMap<>();
64-
70+
Map<State, List<Card>> cardsToMove = new EnumMap<>(State.class);
6571
for (List<Card> cardList : cards.values()) {
6672
List<Card> learnCards = new ArrayList<>();
6773
List<Card> reviseCards = new ArrayList<>();
68-
6974
for (Card card : cardList) {
7075
State category = card.getCategory(this);
71-
7276
if (category == State.LEARN || category == State.REVISE) {
7377
continue;
7478
}
75-
7679
boolean reviseViolated = Intervals.isReviseViolated(card.getLearnDate(), card.getReviseDates());
7780
boolean needRevise = Intervals.needRevise(card.getLearnDate(), Arrays.stream(card.getReviseDates()).max().orElse(0));
78-
7981
if (reviseViolated) {
8082
card.setLearnDate(0);
8183
card.setReviseDates(new long[0]);
@@ -84,33 +86,29 @@ public void updateCards() {
8486
reviseCards.add(card);
8587
}
8688
}
87-
8889
cardList.removeAll(learnCards);
8990
cardList.removeAll(reviseCards);
90-
9191
cardsToMove.computeIfAbsent(State.LEARN, k -> new ArrayList<>()).addAll(learnCards);
9292
cardsToMove.computeIfAbsent(State.REVISE, k -> new ArrayList<>()).addAll(reviseCards);
9393
}
94-
9594
for (Map.Entry<State, List<Card>> entry : cardsToMove.entrySet()) {
9695
cards.get(entry.getKey()).addAll(entry.getValue());
9796
}
97+
invalidateAllCardsCache();
9898
}
9999

100100
public void checkCard(Card card, double grade) {
101101
State currentState = card.getCategory(this);
102-
103102
if (currentState == State.LEARN) {
104103
card.setLearnDate(Time.getUnix());
105104
moveCard(card, State.WEAK);
106105
return;
107106
}
108107
if (currentState == State.REVISE) {
109-
int revises = card.getReviseDates().length;
110-
long[] newReviseDates = Arrays.copyOf(card.getReviseDates(), revises + 1);
111-
newReviseDates[revises] = Time.getUnix();
112-
card.setReviseDates(newReviseDates);
113-
if (revises == 0) {
108+
List<Long> reviseDates = new ArrayList<>(Arrays.asList(Arrays.stream(card.getReviseDates()).boxed().toArray(Long[]::new)));
109+
reviseDates.add(Time.getUnix());
110+
card.setReviseDates(reviseDates.stream().mapToLong(Long::longValue).toArray());
111+
if (reviseDates.size() == 1) {
114112
moveCard(card, State.WEAK);
115113
} else {
116114
moveCard(card, grade >= 0.80 ? State.STRONG : grade <= 0.6 ? State.WEAK : State.MIDDLE);
@@ -135,13 +133,15 @@ public void checkCard(Card card, double grade) {
135133
}
136134

137135
public void updateLevel() {
138-
double grade = Grades.calculateTotalGrade(grades.stream().mapToDouble(Double::doubleValue).toArray());
139-
perSessionCards = Math.min(
140-
grade >= 0.9 ? perSessionCards + 5 : grade >= 0.75 ? perSessionCards + 3 : grade <= 0.6 ? perSessionCards - 5 : perSessionCards,
141-
20
142-
);
143-
perSessionCards = Math.max(perSessionCards, 5);
144-
grades.clear();
136+
if (!grades.isEmpty()) {
137+
double grade = Grades.calculateTotalGrade(grades);
138+
perSessionCards = Math.min(
139+
grade >= 0.9 ? perSessionCards + 3 : grade >= 0.75 ? perSessionCards + 2 : grade <= 0.6 ? perSessionCards - 1 : perSessionCards,
140+
10
141+
);
142+
perSessionCards = Math.max(perSessionCards, 5);
143+
grades.clear();
144+
}
145145
}
146146

147147
public List<Card> getCards() {
@@ -173,13 +173,10 @@ public Map<State, List<Card>> getCategories() {
173173
}
174174

175175
public List<Card> getAllCards() {
176-
List<Card> allCards = new ArrayList<>();
177-
for (List<Card> cards : getCategories().values()) {
178-
for (Card card : cards) {
179-
allCards.add(card);
180-
}
176+
if (allCardsCache == null) {
177+
allCardsCache = cards.values().stream().flatMap(List::stream).collect(Collectors.toList());
181178
}
182-
return allCards;
179+
return allCardsCache;
183180
}
184181

185182
public void setTypeSpeed(int typeSpeed) {
@@ -188,6 +185,7 @@ public void setTypeSpeed(int typeSpeed) {
188185

189186
public void setCards(Map<State, List<Card>> cards) {
190187
this.cards = cards;
188+
invalidateAllCardsCache();
191189
}
192190

193191
public void setGrades(List<Double> grades) {
@@ -197,4 +195,12 @@ public void setGrades(List<Double> grades) {
197195
public void setPerSessionCards(int perSessionCards) {
198196
this.perSessionCards = perSessionCards;
199197
}
200-
}
198+
199+
private void invalidateAllCardsCache() {
200+
allCardsCache = null;
201+
}
202+
203+
public PomodoroTimer getPomodoroTimer() {
204+
return pomodoroTimer;
205+
}
206+
}

0 commit comments

Comments
 (0)