Skip to content

Commit

Permalink
chore: clean up code
Browse files Browse the repository at this point in the history
  • Loading branch information
SuhJae committed Dec 13, 2024
1 parent e22eb90 commit d03b4b1
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 191 deletions.
203 changes: 77 additions & 126 deletions components/CharacterSequencingDemo.vue
Original file line number Diff line number Diff line change
@@ -1,182 +1,141 @@
<script lang="ts" setup>
import { ref, onMounted, computed } from "vue";
const { t } = useI18n();
// Extracted parameters
const characterPool = ref("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
const promptLength = ref(14);
const answerChoiceCount = ref(16 * Math.ceil(promptLength.value / 3));
// State variables
const mainText = ref("");
const subText = ref("");
const prompt = ref("");
const currentTrainingStep = ref(0);
const cursorIndex = ref(0);
const answerChoices = ref<string[]>([]);
const correctIndices = ref<number[]>([]);
const selectedIndices = ref<Set<number>>(new Set());
const missedCount = ref<number>(0);
const correctCount = ref<number>(0);
const selectedIndices = ref(new Set<number>());
const missedCount = ref(0);
const correctCount = ref(0);
const lastCorrectIndex = ref(-1);
const currentTrialCount = ref(1);
// Computed properties
const { t } = useI18n();
const accuracy = computed(() => {
const totalInteractions = correctCount.value + missedCount.value;
return totalInteractions === 0
? 0
: (correctCount.value / totalInteractions) * 100;
const total = correctCount.value + missedCount.value;
return total === 0 ? 0 : (correctCount.value / total) * 100;
});
// Utility function: Wait for specified milliseconds
const waitForMilliseconds = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms));
new Promise((r) => setTimeout(r, ms));
// Function: Generate a prompt
const generatePrompt = () => {
const temp = [];
for (let i = 0; i < promptLength.value; i++) {
const randomIndex = Math.floor(Math.random() * characterPool.value.length);
temp.push(characterPool.value[randomIndex]);
}
return temp.join("");
const getRandomChar = (exclude: string | null) => {
let ch;
do {
ch =
characterPool.value[
Math.floor(Math.random() * characterPool.value.length)
];
} while (ch === exclude);
return ch;
};
// Function: Simulate a trial
const simulateTrial = async () => {
// Reset variables
prompt.value = generatePrompt();
cursorIndex.value = 0;
missedCount.value = 0;
correctCount.value = 0;
lastCorrectIndex.value = -1;
selectedIndices.value.clear();
const promptLen = prompt.value.length;
const indices: number[] = [];
const usedIndices = new Set<number>();
// Randomly assign correct answer positions
while (indices.length < promptLen) {
const index = Math.floor(Math.random() * answerChoiceCount.value);
if (!usedIndices.has(index)) {
usedIndices.add(index);
indices.push(index);
}
}
indices.sort((a, b) => a - b);
answerChoices.value = Array(answerChoiceCount.value).fill(" ");
// Assign correct characters to their positions
indices.forEach((index, i) => {
answerChoices.value[index] = prompt.value[i];
});
// Fill remaining answer choices with random characters, ensuring they don't match adjacent correct characters
for (let i = 0; i < answerChoices.value.length; i++) {
if (answerChoices.value[i] === " ") {
const nextCorrectIdx = indices.find((idx) => idx > i);
const nextPromptChar =
nextCorrectIdx !== undefined
? prompt.value[indices.indexOf(nextCorrectIdx)]
: null;
answerChoices.value[i] = getRandomCharacter(nextPromptChar);
}
const generatePrompt = () => {
let result = "";
for (let i = 0; i < promptLength.value; i++) {
result +=
characterPool.value[
Math.floor(Math.random() * characterPool.value.length)
];
}
correctIndices.value = indices;
// Start trial
mainText.value = "";
subText.value = "";
currentTrainingStep.value = 2;
// Simulate selecting answer choices
await simulateSelections();
// Repeat the trial
simulateTrial();
};
const getRandomCharacter = (excludeChar: string | null) => {
let char;
do {
char = characterPool.value.charAt(
Math.floor(Math.random() * characterPool.value.length)
);
} while (char === excludeChar);
return char;
return result;
};
// Function: Simulate selections based on actual logic
const simulateSelections = async () => {
while (cursorIndex.value < answerChoiceCount.value) {
await waitForMilliseconds(Math.random() * 100 + 150);
// Check for missed correct characters before moving
if (correctIndices.value.includes(cursorIndex.value)) {
const isSelected = Math.random() < 0.95; // 95% chance to select correctly
if (isSelected) {
// Simulate selection
if (Math.random() < 0.95) {
selectedIndices.value.add(cursorIndex.value);
correctCount.value++;
lastCorrectIndex.value = cursorIndex.value;
cursorIndex.value++;
} else {
// Simulate missing the correct selection
missedCount.value++;
cursorIndex.value = lastCorrectIndex.value + 1;
await waitForMilliseconds(Math.random() * 1200 + 600);
}
} else {
const isMistakenSelection = Math.random() < 0.05; // 5% chance to mistakenly select incorrect answer
if (isMistakenSelection) {
// Simulate mistaken selection
if (Math.random() < 0.05) {
missedCount.value++;
// Return cursor to last correct index + 1
cursorIndex.value = lastCorrectIndex.value + 1;
await waitForMilliseconds(Math.random() * 1200 + 600);
} else {
// Move cursor to next index without selection
cursorIndex.value++;
}
}
}
currentTrialCount.value++;
// Trial ends when cursor has traversed all answer choices
// Calculate and display results
currentTrainingStep.value = 3;
mainText.value = t("training.finish");
subText.value = `${t("training.accuracy")} ${accuracy.value.toFixed(2)}%`;
await waitForMilliseconds(2000);
// Reset for next trial
await waitForMilliseconds(2000);
currentTrainingStep.value = 1;
mainText.value = t("training.ready");
subText.value = `${t("training.trial")} #${currentTrialCount.value}`;
await waitForMilliseconds(1000);
// Countdown before next trial
await waitForMilliseconds(1000);
for (let i = 3; i > 0; i--) {
mainText.value = i.toString();
await waitForMilliseconds(1000);
}
// Restart the trial
currentTrainingStep.value = 2;
mainText.value = "";
subText.value = "";
};
// Optional: Initialize the first trial on component mount
const simulateTrial = async () => {
prompt.value = generatePrompt();
cursorIndex.value = 0;
missedCount.value = 0;
correctCount.value = 0;
lastCorrectIndex.value = -1;
selectedIndices.value.clear();
const len = prompt.value.length;
const used = new Set<number>();
const indices: number[] = [];
while (indices.length < len) {
const idx = Math.floor(Math.random() * answerChoiceCount.value);
if (!used.has(idx)) {
used.add(idx);
indices.push(idx);
}
}
indices.sort((a, b) => a - b);
answerChoices.value = Array(answerChoiceCount.value).fill(" ");
indices.forEach((x, i) => (answerChoices.value[x] = prompt.value[i]));
for (let i = 0; i < answerChoices.value.length; i++) {
if (answerChoices.value[i] === " ") {
const nx = indices.find((idx) => idx > i);
answerChoices.value[i] = getRandomChar(
nx !== undefined ? prompt.value[indices.indexOf(nx)] : null
);
}
}
correctIndices.value = indices;
currentTrainingStep.value = 2;
mainText.value = "";
subText.value = "";
await simulateSelections();
simulateTrial();
};
onMounted(() => {
simulateTrial();
});
Expand All @@ -185,25 +144,19 @@ onMounted(() => {
<template>
<div class="overflow-hidden bg-zinc-50 dark:bg-zinc-950 w-full h-full p-4">
<div
class="flex flex-col justify-center items-center h-full space-y-10"
v-if="currentTrainingStep === 1 || currentTrainingStep === 3"
class="flex flex-col justify-center items-center h-full space-y-10"
>
<TitleHud :title="mainText" :subtitle="subText" />
</div>

<div
class="flex flex-col justify-center items-center h-full training-text"
v-if="currentTrainingStep === 2"
class="flex flex-col justify-center items-center h-full training-text"
>
<div class="flex">
<div
class="flex justify-center w-8"
v-for="(char, index) in prompt"
:key="index"
>
<span class="block text-center text-4xl">
{{ char }}
</span>
<div v-for="(ch, i) in prompt" :key="i" class="flex justify-center w-8">
<span class="block text-center text-4xl">{{ ch }}</span>
</div>
</div>

Expand All @@ -212,7 +165,7 @@ onMounted(() => {
<div class="flex justify-center">
<div class="grid grid-cols-16">
<div
v-for="(char, i) in answerChoices"
v-for="(ch, i) in answerChoices"
:key="i"
:id="'choice-' + i"
:class="[
Expand All @@ -224,9 +177,7 @@ onMounted(() => {
},
]"
>
<span class="block text-center text-5xl w-full">
{{ char }}
</span>
<span class="block text-center text-5xl w-full">{{ ch }}</span>
</div>
</div>
</div>
Expand Down
23 changes: 8 additions & 15 deletions components/ImagePlaceholder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch, nextTick } from "vue";
import { ref, onMounted, onBeforeUnmount } from "vue";
const scalingContainer = ref(null);
const demoWrapper = ref(null);
Expand All @@ -24,18 +24,14 @@ const maxWidth = 862;
const maxHeight = 470;
const calculateScale = () => {
if (scalingContainer.value && demoWrapper.value) {
const parentWidth = scalingContainer.value.clientWidth;
const parentHeight = scalingContainer.value.clientHeight;
const container = scalingContainer.value;
const wrapper = demoWrapper.value;
if (!container || !wrapper) return;
const widthScale = parentWidth / maxWidth;
const heightScale = parentHeight / maxHeight;
const { clientWidth, clientHeight } = container;
const scale = Math.min(clientWidth / maxWidth, clientHeight / maxHeight, 1);
const scale = Math.min(widthScale, heightScale, 1); // Ensure scale doesn't exceed 1
demoWrapper.value.style.transform = `scale(${scale})`;
demoWrapper.value.style.transformOrigin = "top left";
}
wrapper.style.transform = `scale(${scale})`;
};
onMounted(() => {
Expand All @@ -53,7 +49,6 @@ onBeforeUnmount(() => {
--angle: 0deg;
--border-color: rgb(var(--color-gray-300));
--highlight-color: rgb(var(--color-primary-500));
content: "";
position: absolute;
top: 0;
Expand All @@ -65,7 +60,6 @@ onBeforeUnmount(() => {
border-radius: 0.8rem;
z-index: -1;
background: var(--border-color);
@supports (background: paint(houdini)) {
background: linear-gradient(
var(--angle),
Expand Down Expand Up @@ -96,7 +90,6 @@ onBeforeUnmount(() => {
inherits: false;
}
/* Scaling Styles */
.scaling-container {
width: 100%;
height: 100%;
Expand All @@ -107,9 +100,9 @@ onBeforeUnmount(() => {
.demo-wrapper {
width: 862px;
height: 470px;
/* Optional: To center the scaled content */
display: flex;
justify-content: center;
align-items: center;
transform-origin: top left;
}
</style>
2 changes: 0 additions & 2 deletions components/LangSwitcher.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
<NuxtImg
class="h-4 w-auto"
:src="'/flags/' + selectedLang + '.svg'"
loading="lazy"
:alt="selectedLang"
/>
</span>
Expand All @@ -19,7 +18,6 @@
<NuxtImg
class="h-4 w-auto"
:src="'/flags/' + option.code + '.svg'"
loading="lazy"
:alt="option.code"
/>
<span class="truncate">{{ option.label }}</span>
Expand Down
Loading

0 comments on commit d03b4b1

Please sign in to comment.