Skip to content
Snippets Groups Projects
Commit 70b2e14b authored by bedran.sezer's avatar bedran.sezer Committed by michael.minelli
Browse files

update fuzzy matching

parent 47750aa8
No related branches found
No related tags found
No related merge requests found
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
\ No newline at end of file
#/-------------------.env.vault---------------------/
#/ cloud-agnostic vaulting standard /
#/ [how it works](https://dotenvx.com/env-vault) /
#/ [how it works](https://dotenv.org/env-vault) /
#/--------------------------------------------------/
# development
......
......@@ -2,7 +2,6 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
<mapping directory="$PROJECT_DIR$/DojoExercise_Technique_de compilation - TP" vcs="Git" />
<mapping directory="$PROJECT_DIR$/src/shared" vcs="Git" />
<mapping directory="$PROJECT_DIR$/src/sharedByClients" vcs="Git" />
</component>
......
......@@ -3,6 +3,7 @@ import ExerciseCreateCommand from './subcommands/ExerciseCreateCommand.js';
import ExerciseRunCommand from './subcommands/ExerciseRunCommand.js';
import ExerciseCorrectionCommand from './subcommands/ExerciseCorrectionCommand.js';
import ExerciseDeleteCommand from './subcommands/ExerciseDeleteCommand';
import ExerciseListCommand from "./subcommands/ExerciseListCommand";
class ExerciseCommand extends CommanderCommand {
......@@ -18,6 +19,7 @@ class ExerciseCommand extends CommanderCommand {
ExerciseRunCommand.registerOnCommand(this.command);
ExerciseDeleteCommand.registerOnCommand(this.command);
ExerciseCorrectionCommand.registerOnCommand(this.command);
ExerciseListCommand.registerOnCommand(this.command);
}
protected async commandAction(): Promise<void> {
......
// ExerciseListCommand.ts
import CommanderCommand from '../../CommanderCommand';
import chalk from 'chalk';
import ora from 'ora';
import DojoBackendManager from '../../../managers/DojoBackendManager';
import AccessesHelper from '../../../helpers/AccessesHelper';
import Exercise from '../../../sharedByClients/models/Exercise';
import inquirer from 'inquirer';
import Table from 'cli-table3';
import Fuse from 'fuse.js';
import User from '../../../sharedByClients/models/User';
class ExerciseListCommand extends CommanderCommand {
protected commandName: string = 'list';
protected defineCommand(): void {
this.command
.description('list your exercises')
.action(this.commandAction.bind(this));
}
protected async commandAction(): Promise<void> {
console.log(chalk.cyan('Please wait while we retrieve your exercises...'));
// Check access
if (!await AccessesHelper.checkStudent()) {
return;
}
// Fetch user's exercises
const userExercises: Exercise[] | undefined = await DojoBackendManager.getUserExercises();
if (!userExercises || userExercises.length === 0) {
ora().info('You have no exercises yet.');
return;
}
// Display the list of exercises
this.displayExerciseList(userExercises);
// Ask the user for further actions
await this.askUserForActions(userExercises);
}
private async askUserForActions(exercises: Exercise[]): Promise<void> {
const { action } = await inquirer.prompt([
{
type: 'list',
name: 'action',
message: 'Que souhaitez-vous faire ?',
choices: [
{ name: 'Voir les détails d\'exercice', value: 'details'},
{ name: 'Filter les exercises', value: 'filter' },
{ name: 'Exit', value: 'exit' },
],
},
]);
if (action === 'details') {
await this.selectExerciseForDetails(exercises);
} else if (action === 'filter') {
await this.filterExercises(exercises);
} else {
ora().info('No further actions selected.');
}
}
private async selectExerciseForDetails(exercises: Exercise[]): Promise<void> {
const { selectedExercise } = await inquirer.prompt([{
type: 'list',
name: 'selectedExercise',
message: 'Selectionner un exercice :',
choices: [
...exercises.map(exercise => ({
name: exercise.name,
value: exercise.id,
})),
{ name: 'Exit', value: 'exit' },
],
}]);
if (selectedExercise === 'exit') {
ora().info('Pas de détails requis: détails dispo avec la commande `dojo exercise info <id>`.');
return;
}
const selected = exercises.find(ex => ex.id === selectedExercise);
if (selected) {
await this.displayExerciseDetails(selected);
} else {
ora().info('Invalid selection. No exercise details to show.');
}
}
private async filterExercises(exercises: Exercise[]): Promise<void> {
const { filterType } = await inquirer.prompt([
{
type: 'list',
name: 'filterType',
message: 'Comment souhaitez-vous filtrer les exercices ?',
choices: [
{ name: 'Par saisie texte', value: 'fuzzy' },
{ name: 'Par professeurs', value: 'professor' },
{ name: 'Exit', value: 'exit' },
],
},
]);
if (filterType === 'fuzzy') {
await this.fuzzySearchExercises(exercises);
} else if (filterType === 'professor') {
await this.filterByProfessor(exercises);
} else {
ora().info('No filtering selected.');
}
}
private async fuzzySearchExercises(exercises: Exercise[]): Promise<void> {
const { searchQuery } = await inquirer.prompt([
{
type: 'input',
name: 'searchQuery',
message: 'Entrez le nom de l\'exercice (laisser vide pour la liste complète) :',
},
]);
if (!searchQuery) {
this.displayExerciseList(exercises);
return;
}
const fuse = new Fuse(exercises, {
keys: ['name'],
threshold: 0.5,
distance: 150,
});
const searchResults = fuse.search(searchQuery).map(result => result.item);
if (searchResults.length === 0) {
ora().info('Aucun exercice trouvé correspondant à votre recherche.');
return;
}
if (searchResults.length === 1) {
// Display details and members for the single matching exercise
const singleExercise = searchResults[0];
this.displayExerciseDetails(singleExercise);
} else {
// Display only exercise names and info about viewing details
ora().info(' Plusieurs exercices trouvés correspondant à votre recherche :');
const exerciseNames = searchResults.map(exercise => exercise.name);
console.log(' ', exerciseNames.join('\n '));
ora().info('Les détails sont disponibles avec la commande : `dojo exercise info <id>`.');
}
}
private async filterByProfessor(exercises: Exercise[]): Promise<void> {
const professors: User[] | undefined = await DojoBackendManager.getProfessors();
if (!professors || professors.length === 0) {
ora().info('No professors found.');
return;
}
const professorChoices = professors.map(professor => ({
name: `${professor.gitlabUsername}`,
value: professor // Use the professor object as the value
}));
const { selectedProfessor } = await inquirer.prompt([
{
type: 'list',
name: 'selectedProfessor',
message: 'Selectionnez un professeur:',
choices: professorChoices
}
]);
console.log(`Selected professor: ${selectedProfessor.gitlabUsername}`);
ora().info('Filter by professor is not yet implemented.');
}
private displayExerciseList(exercises: Exercise[]): void {
const headers = ['Exercise Name', 'GitLab Link'];
// Calculate the maximum width for each column
const maxWidths = headers.map(header => header.length);
exercises.forEach(exercise => {
maxWidths[0] = Math.max(maxWidths[0], exercise.name.length);
maxWidths[1] = Math.max(maxWidths[1], exercise.gitlabLink.length);
});
const table = new Table({
head: headers,
});
exercises.forEach((exercise) => {
table.push([
exercise.name,
exercise.gitlabLink,
]);
});
ora().info('Your exercises:');
console.log(table.toString());
}
private async displayExerciseDetails(exercise: Exercise): Promise<void> {
ora().info(`Detail of Exercise with ID: ${exercise.id}`);
console.log(chalk.magenta(' - Exercise Name:'), exercise.name);
console.log(chalk.magenta(' - Assignment Name:'), exercise.assignmentName);
console.log(chalk.magenta(' - GitLab ID:'), exercise.gitlabId);
console.log(chalk.magenta(' - GitLab Link:'), chalk.blue.underline(exercise.gitlabLink));
console.log(chalk.magenta(' - GitLab Last Info Date:'), exercise.gitlabLastInfoDate);
// Fetch exercise members
const exerciseMembers = await DojoBackendManager.getExerciseMembers(exercise.id);
if (exerciseMembers && exerciseMembers.length > 0) {
ora().info('Exercise Members:');
exerciseMembers.forEach(member => {
console.log(chalk.magenta(` - ${member.id} ${member.name}`));
});
} else {
ora().info('No members found for this exercise.');
}
}
}
export default new ExerciseListCommand();
\ No newline at end of file
......@@ -554,6 +554,17 @@ class DojoBackendManager {
public async getTeachers(): Promise<Array<User> | undefined> {
return this.getUsers('teacher');
}
public async getExerciseDetail(exerciseId: string): Promise<Exercise | undefined> {
try {
const response = await axios.get<Exercise>(DojoBackendHelper.getApiUrl(ApiRoute.EXERCISE_DETAIL).replace('{{exerciseId}}', String(exerciseId)));
return response.data;
} catch ( error ) {
console.error('Error fetching exercise details:', error);
return undefined;
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment