Skip to content

Commit

Permalink
Implement voting mechanism (#441)
Browse files Browse the repository at this point in the history
feat: votes and ratings

implement settings for steps, votes, flexible ratings and results views for votes

test: refactor tests and selectors
fix: make Vote as default value for results
  • Loading branch information
swouf authored Sep 20, 2024
1 parent 221466b commit f01aac4
Show file tree
Hide file tree
Showing 60 changed files with 1,815 additions and 1,140 deletions.
21 changes: 13 additions & 8 deletions cypress/e2e/builder/main.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { Context, PermissionLevel } from '@graasp/sdk';
import {
ADMIN_PANEL_CY,
BUILDER_VIEW_CY,
NEXT_ROUND_BTN_CY,
PLAY_PAUSE_BUTTON_CY,
ORCHESTRATION_BAR_CY,
PROPOSE_NEW_RESPONSE_BTN_CY,
RESPONSE_COLLECTION_VIEW_CY,
SETTINGS_TAB_CY,
Expand All @@ -29,19 +28,25 @@ describe('Builder View with admin rights, no settings', () => {

it('loads the view without initialization', () => {
cy.get(buildDataCy(BUILDER_VIEW_CY));
cy.get(buildDataCy(ADMIN_PANEL_CY)).should('exist');
cy.get(buildDataCy(ADMIN_PANEL_CY)).should('not.exist');
});

it('starts the ideation process with orchestrator', () => {
cy.get(buildDataCy(PLAY_PAUSE_BUTTON_CY)).should('have.lengthOf', 1);
cy.get(buildDataCy(PLAY_PAUSE_BUTTON_CY)).click();
cy.get(buildDataCy(ORCHESTRATION_BAR_CY.PLAY_BUTTON)).should(
'have.lengthOf',
1,
);
cy.get(buildDataCy(ORCHESTRATION_BAR_CY.PLAY_BUTTON)).click();

cy.get(buildDataCy(RESPONSE_COLLECTION_VIEW_CY)).should('exist');
});

it('create some responses, and hit next round', () => {
cy.get(buildDataCy(PLAY_PAUSE_BUTTON_CY)).should('have.lengthOf', 1);
cy.get(buildDataCy(PLAY_PAUSE_BUTTON_CY)).click();
cy.get(buildDataCy(ORCHESTRATION_BAR_CY.PLAY_BUTTON)).should(
'have.lengthOf',
1,
);
cy.get(buildDataCy(ORCHESTRATION_BAR_CY.PLAY_BUTTON)).click();

const newIdeas = ['Testing this software', "I don't know.", 'Sleep...'];

Expand All @@ -56,7 +61,7 @@ describe('Builder View with admin rights, no settings', () => {
});
});

cy.get(buildDataCy(NEXT_ROUND_BTN_CY)).click();
cy.get(buildDataCy(ORCHESTRATION_BAR_CY.NEXT_STEP_BTN)).click();
});

it('visits settings', () => {
Expand Down
29 changes: 13 additions & 16 deletions cypress/e2e/player/main.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@ import { Context, PermissionLevel } from '@graasp/sdk';
import {
ADMIN_PANEL_CY,
DETAILS_INSTRUCTIONS_CY,
LIKERT_RATING_CY,
NEXT_STEP_BTN_CY,
ORCHESTRATION_BAR_CY,
PROMPTS_CY,
PROPOSE_NEW_RESPONSE_BTN_CY,
RESPONSE_COLLECTION_VIEW_CY,
RESPONSE_CY,
RESPONSE_EVALUATION_VIEW_CY,
RESPONSE_RESULTS_VIEW_CY,
TITLE_INSTRUCTIONS_CY,
Expand Down Expand Up @@ -120,28 +117,28 @@ describe('Player with read rights, configured with one assistant and no data.',
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(MEAN_WAITING_TIME);
cy.get(buildDataCy(RESPONSE_COLLECTION_VIEW_CY)).should('exist');
cy.get(buildDataCy(NEXT_STEP_BTN_CY)).click();
cy.get(buildDataCy(ORCHESTRATION_BAR_CY.NEXT_STEP_BTN)).click();
cy.get(buildDataCy(RESPONSE_COLLECTION_VIEW_CY)).should('exist');

// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(MEAN_WAITING_TIME);
cy.get(buildDataCy(NEXT_STEP_BTN_CY)).click();
cy.get(buildDataCy(ORCHESTRATION_BAR_CY.NEXT_STEP_BTN)).click();
cy.get(buildDataCy(RESPONSE_EVALUATION_VIEW_CY)).should('exist');

// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(MEAN_WAITING_TIME);

cy.get(buildDataCy(RESPONSE_CY))
.first()
.within(() => {
cy.get(buildDataCy(LIKERT_RATING_CY))
.first()
.within(() => {
cy.get('input[value=5]').click({ force: true });
});
});

cy.get(buildDataCy(NEXT_STEP_BTN_CY)).click();
// cy.get(buildDataCy(RESPONSE_CY))
// .first()
// .within(() => {
// cy.get(buildDataCy(LIKERT_RATING_CY))
// .first()
// .within(() => {
// cy.get('input[value=5]').click({ force: true });
// });
// });

cy.get(buildDataCy(ORCHESTRATION_BAR_CY.NEXT_STEP_BTN)).click();

cy.get(buildDataCy(RESPONSE_RESULTS_VIEW_CY)).should('exist');
});
Expand Down
7 changes: 5 additions & 2 deletions cypress/fixtures/appSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { AppSetting } from '@graasp/sdk';

import { AllSettingsType } from '@/config/appSettingsType';
import { DEFAULT_SYSTEM_PROMPT } from '@/config/prompts';
import { EvaluationType } from '@/interfaces/evaluationType';
import {
ActivityType,
ResponseVisibilityMode,
} from '@/interfaces/interactionProcess';

import { EvaluationType } from '@/interfaces/evaluation';
import { MEMBERS } from './members';
import { MOCK_SERVER_DISCRIMINATED_ITEM } from './mockItem';

Expand Down Expand Up @@ -63,7 +63,6 @@ export const ALL_SETTINGS_OBJECT: AllSettingsType = {
numberOfResponsesPerSet: 3,
numberOfBotResponsesPerSet: 1,
exclusiveResponseDistribution: true,
evaluationType: EvaluationType.UsefulnessNoveltyRating,
steps: [
{
type: ActivityType.Collection,
Expand Down Expand Up @@ -130,6 +129,10 @@ SETTINGS_WITH_ASSISTANT_OBJECT.activity.steps = [
type: ActivityType.Evaluation,
round: 2,
time: 1,
evaluationType: EvaluationType.Vote,
evaluationParameters: {
maxNumberOfVotes: 3,
},
},
{
type: ActivityType.Results,
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"date-fns": "^3.3.1",
"i18next": "23.15.1",
"liquidjs": "^10.10.1",
"lodash.clone": "^4.5.0",
"lodash.isequal": "^4.5.0",
"lodash.shuffle": "^4.2.0",
"plotly.js": "^2.29.1",
Expand Down Expand Up @@ -84,6 +85,8 @@
"@trivago/prettier-plugin-sort-imports": "4.3.0",
"@types/d3": "^7.4.3",
"@types/i18n": "0.13.12",
"@types/lodash": "^4.17.7",
"@types/lodash.clone": "^4",
"@types/lodash.clonedeep": "^4.5.9",
"@types/lodash.isequal": "^4.5.8",
"@types/lodash.shuffle": "^4.2.9",
Expand Down
16 changes: 6 additions & 10 deletions src/config/appActionsTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@ import { AppAction, AppData } from '@graasp/sdk';

import { ActivityStep } from '@/interfaces/interactionProcess';
import { Prompt } from '@/interfaces/prompt';
import {
CurrentStateData,
RatingsData,
ResponseAppData,
ResponseData,
} from './appDataTypes';
import { ResponseData } from '@/interfaces/response';
import { CurrentStateData, ResponseAppData } from './appDataTypes';

export enum AppActionTypes {
SubmitNewResponse = 'submit-new-response',
Expand Down Expand Up @@ -51,10 +47,10 @@ export type OpenAppAction = Pick<AppAction, 'type' | 'data'> & {
};
};

export type EvaluateResponseAction<T> = Pick<AppAction, 'type' | 'data'> & {
type: AppActionTypes.EvaluateResponse;
data: AppDataRef<RatingsData<T>>;
};
// export type EvaluateResponseAction<T> = Pick<AppAction, 'type' | 'data'> & {
// type: AppActionTypes.EvaluateResponse;
// data: AppDataRef<RatingsData<T>>;
// };

type StepAction = Pick<AppAction, 'type' | 'data'> & {
data: ActivityStep & { stepIndex: number };
Expand Down
57 changes: 29 additions & 28 deletions src/config/appDataTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,29 @@ import { AppData, AppDataVisibility } from '@graasp/sdk';

import { AssistantId } from '@/interfaces/assistant';
import { ChatbotResponseData } from '@/interfaces/chatbot';
import { EvaluationType } from '@/interfaces/evaluationType';
import { ActivityStatus, ActivityType } from '@/interfaces/interactionProcess';
import { UsefulnessNoveltyRatings } from '@/interfaces/ratings';
import { PromptsData } from '@/interfaces/prompt';
import { EvaluationParameters } from '@/interfaces/evaluation';
import { ResponseData, ResponseEvaluation } from '@/interfaces/response';

export enum AppDataTypes {
Response = 'response',
ResponsesSet = 'responses-set',
CurrentState = 'current-state',
Ratings = 'ratings',
Evaluation = 'evaluation',
Ranking = 'ranking',
Rating = 'rating',
Vote = 'Vote',
ChatbotResponse = 'chatbot-response',
Prompts = 'prompts',
}

export type ResponseData<T = UsefulnessNoveltyRatings> = {
response: string | Array<string>;
round?: number;
bot?: boolean;
assistantId?: AssistantId;
parentId?: string;
encoding?: 'raw' | 'markdown';
originalResponse?: string;
ratings?: T;
givenPrompt?: string;
};

export type ResponseAppData = AppData & {
type: AppDataTypes.Response;
data: ResponseData;
visibility: AppDataVisibility.Item;
};
export type ResponseAppData<T extends ResponseEvaluation = undefined> =
AppData & {
type: AppDataTypes.Response;
data: ResponseData<T>;
visibility: AppDataVisibility.Item;
};

export type ResponsesSetAppData = AppData & {
type: AppDataTypes.ResponsesSet;
Expand All @@ -56,16 +48,25 @@ export type CurrentStateAppData = AppData & {
data: CurrentStateData;
};

export type RatingsData<T> = {
ideaRef: string;
type: EvaluationType;
ratings: T;
export type RatingData = {
responseRef: string;
name: EvaluationParameters['ratingsName'];
ratings: Array<{
name: string;
value: number;
}>;
};

export type RatingsAppData<T> = AppData & {
type: AppDataTypes.Ratings;
data: RatingsData<T>;
visibility: AppDataVisibility.Member;
export type RatingAppData = AppData & {
type: AppDataTypes.Rating;
data: RatingData;
visibility: AppDataVisibility.Item;
};

export type VoteAppData = AppData & {
type: AppDataTypes.Vote;
data: { responseRef: string };
visibility: AppDataVisibility.Item;
};

export type ChatbotResponseAppData = AppData & {
Expand Down
3 changes: 0 additions & 3 deletions src/config/appSettingsType.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Member } from '@graasp/sdk';

import { AssistantPersona, PromptMode } from '@/interfaces/assistant';
import { EvaluationType } from '@/interfaces/evaluationType';
import {
ActivityStep,
ActivityType,
Expand Down Expand Up @@ -37,7 +36,6 @@ export type ActivitySetting = {
numberOfResponsesPerSet: number;
numberOfBotResponsesPerSet: number;
exclusiveResponseDistribution: boolean;
evaluationType: EvaluationType;
steps: ActivityStep[];
reformulateResponses: boolean;
};
Expand Down Expand Up @@ -97,7 +95,6 @@ export const defaultSettingsValues: AllSettingsType = {
numberOfResponsesPerSet: 3,
numberOfBotResponsesPerSet: 1,
exclusiveResponseDistribution: false,
evaluationType: EvaluationType.UsefulnessNoveltyRating,
reformulateResponses: false,
steps: [
{
Expand Down
3 changes: 3 additions & 0 deletions src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { AppDataVisibility } from '@graasp/sdk';

import { ActivityStatus, ActivityType } from '@/interfaces/interactionProcess';

import { EvaluationType } from '@/interfaces/evaluation';
import {
AppDataTypes,
ChatbotResponseAppData,
Expand Down Expand Up @@ -46,6 +47,8 @@ export const DEFAULT_BOT_USERNAME = 'GraaspBot';
export const SHORT_TIME_LIMIT = 10; // seconds
export const DEFAULT_LANG = 'en';

export const DEFAULT_EVALUATION_TYPE = EvaluationType.Vote;

export const CATEGORY_COLORS = [
'#ffadad',
'#ffd6a5',
Expand Down
Empty file.
26 changes: 26 additions & 0 deletions src/config/ratings/Ratings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { RatingDescription } from '@/interfaces/evaluation';

export const UsefulnessNoveltyRating: Array<RatingDescription> = [
{
name: 'Usefulness',
description: 'How useful is the response',
maxLabel: 'Useful',
minLabel: 'Useless',
levels: 5,
},
{
name: 'Novelty',
description: 'How novel is the response',
maxLabel: 'Novel',
minLabel: 'Common',
levels: 5,
},
];

export const RatingsSet = [
{
name: 'Usefulness and novelty',
description: 'How useful and novel is this response',
set: UsefulnessNoveltyRating,
},
];
8 changes: 4 additions & 4 deletions src/config/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export const RESPONSE_COLLECTION_VIEW_CY = 'response-collection-view';
export const RESPONSE_EVALUATION_VIEW_CY = 'response-evaluation-view';
export const RESPONSE_RESULTS_VIEW_CY = 'response-results-view';
export const ADMIN_PANEL_CY = 'admin-panel';
export const PLAY_PAUSE_BUTTON_CY = 'play-pause-button';
export const INITIALIZE_BTN_CY = 'initialize-button';
export const CODE_EDITOR_ID_CY = 'code-editor-id';
export const SETTING_CHATBOT_PROMPT_CODE_EDITOR_CY =
Expand All @@ -28,15 +27,16 @@ export const TITLE_INSTRUCTIONS_CY = 'title-instructions';
export const ORCHESTRATION_BAR_CY = {
PLAY_BUTTON: 'orchestration-bar-play-button',
PAUSE_BUTTON: 'orchestration-bar-pause-button',
PREVIOUS_STEP_BTN: 'orchestration-bar-previous-step-btn',
NEXT_STEP_BTN: 'orchestration-bar-next-step-btn',
};

export const PREVIOUS_STEP_BTN_CY = 'previous-step-btn';
export const NEXT_STEP_BTN_CY = 'next-step-btn';

export const RESPONSE_CY = 'response';

export const LIKERT_RATING_CY = 'likert-rating';

export const EVALUATION_RATE_CY = 'evaluation-rate-component-actions';

export const PROMPTS_CY = {
REQUEST_BUTTON: 'prompts-request-button',
PROMPT_STEP: 'prompt-step-indicator',
Expand Down
Loading

0 comments on commit f01aac4

Please sign in to comment.