Skip to content

Commit

Permalink
Merge pull request #29 from PAIR-code/all-items
Browse files Browse the repository at this point in the history
All items added, with their images, seed the database with 5 random pairs
  • Loading branch information
GnRlLeclerc committed May 21, 2024
2 parents a2d87d4 + d641929 commit 68c53c4
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 57 deletions.
34 changes: 16 additions & 18 deletions functions/src/seeders/stages.seeder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@ export class StagesSeeder {
id: '1',
questionText: 'Rate the items by how helpful they would be for survival.',
item1: {
name: 'compas',
name: 'shavingMirror',
imageUrl:
'https://m.media-amazon.com/images/I/81NUeKWdiQL._AC_UF1000,1000_QL80_.jpg',
'https://upload.wikimedia.org/wikipedia/commons/3/32/Mirror%2C_shaving_%28AM_880330-3%29.jpg',
},
item2: {
name: 'blanket',
imageUrl:
'https://img.freepik.com/free-psd/blanket-isolated-transparent-background_191095-10098.jpg?size=338&ext=jpg&ga=GA1.1.1700460183.1712448000&semt=sph',
name: 'sextant',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Sextant_von_Alexander_von_Humboldt.jpg/640px-Sextant_von_Alexander_von_Humboldt.jpg',
},
choice: null,
confidence: null,
Expand Down Expand Up @@ -59,18 +58,18 @@ export class StagesSeeder {
messages: [],
items: [
{
name: 'compas',
imageUrl: 'https://m.media-amazon.com/images/I/81NUeKWdiQL._AC_UF1000,1000_QL80_.jpg',
name: 'shavingMirror',
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/3/32/Mirror%2C_shaving_%28AM_880330-3%29.jpg',
},
{
name: 'blanket',
imageUrl:
'https://img.freepik.com/free-psd/blanket-isolated-transparent-background_191095-10098.jpg?size=338&ext=jpg&ga=GA1.1.1700460183.1712448000&semt=sph',
name: 'sextant',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Sextant_von_Alexander_von_Humboldt.jpg/640px-Sextant_von_Alexander_von_Humboldt.jpg',
},
{
name: 'lighter',
name: 'mosquitoNetting',
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/White_lighter_with_flame.JPG/1200px-White_lighter_with_flame.JPG',
'https://commons.wikimedia.org/wiki/Category:Mosquito_nets#/media/File:Net,_mosquito_(AM_2015.20.7-1).jpg',
},
],
readyToEndChat: false,
Expand Down Expand Up @@ -121,14 +120,13 @@ export class StagesSeeder {
id: '5',
questionText: 'Please rating the following accoring to which is best for survival',
item1: {
name: 'compas',
imageUrl:
'https://m.media-amazon.com/images/I/81NUeKWdiQL._AC_UF1000,1000_QL80_.jpg',
name: 'shavingMirror',
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/3/32/Mirror%2C_shaving_%28AM_880330-3%29.jpg',
},
item2: {
name: 'blanket',
imageUrl:
'https://img.freepik.com/free-psd/blanket-isolated-transparent-background_191095-10098.jpg?size=338&ext=jpg&ga=GA1.1.1700460183.1712448000&semt=sph',
name: 'sextant',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Sextant_von_Alexander_von_Humboldt.jpg/640px-Sextant_von_Alexander_von_Humboldt.jpg',
},
choice: null,
confidence: null,
Expand Down
2 changes: 1 addition & 1 deletion scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
"devDependencies": {
"@types/node": "^20.12.7"
}
}
}
44 changes: 22 additions & 22 deletions scripts/src/seed-database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ import {
ChatKind,
Experiment,
ExperimentTemplate,
ITEM_NAMES,
RatingQuestionConfig,
StageConfig,
StageKind,
SurveyQuestionKind,
choices,
getDefaultProfile,
pairs,
participantPublicId,
seed,
} from '@llm-mediation-experiments/utils';
import { Timestamp } from 'firebase-admin/firestore';
import admin, { initializeApp } from './admin';

initializeApp();

seed(585050400); // Seed the random number generator

const seedDatabase = async () => {
const db = admin.firestore();

Expand Down Expand Up @@ -80,6 +87,17 @@ const seedDatabase = async () => {
// ********************************************************************************************* //
// SEEDER DATA //
// ********************************************************************************************* //
const RANDOM_ITEM_PAIRS = choices(pairs(ITEM_NAMES), 5);

const RATING_QUESTION_CONFIGS: RatingQuestionConfig[] = RANDOM_ITEM_PAIRS.map(
([item1, item2], id) => ({
id,
kind: SurveyQuestionKind.Rating,
questionText: 'Rate the items by how helpful they would be for survival.',
item1,
item2,
}),
);

const DEFAULT_STAGES: Record<string, StageConfig> = {
'1. Agree to the experiment and set your profile': {
Expand All @@ -96,15 +114,9 @@ const DEFAULT_STAGES: Record<string, StageConfig> = {
name: '2. Initial leadership survey',
kind: StageKind.TakeSurvey,
questions: [
...RATING_QUESTION_CONFIGS,
{
id: 0,
kind: SurveyQuestionKind.Rating,
questionText: 'Rate the items by how helpful they would be for survival.',
item1: 'compas',
item2: 'blanket',
},
{
id: 1,
id: 99, // Avoid collision with rating questions id (starting from 0)
kind: SurveyQuestionKind.Scale,
questionText: 'Rate the how much you would like to be the group leader.',
lowerBound: 'I would most definitely not like to be the leader (0/10)',
Expand All @@ -119,11 +131,7 @@ const DEFAULT_STAGES: Record<string, StageConfig> = {
chatId: 'chat-0',
chatConfig: {
kind: ChatKind.ChatAboutItems,
ratingsToDiscuss: [
{ item1: 'blanket', item2: 'compas' },
{ item1: 'blanket', item2: 'lighter' },
{ item1: 'lighter', item2: 'compas' },
],
ratingsToDiscuss: RANDOM_ITEM_PAIRS.map(([i1, i2]) => ({ item1: i1, item2: i2 })),
},
},

Expand Down Expand Up @@ -164,15 +172,7 @@ const DEFAULT_STAGES: Record<string, StageConfig> = {
'7. Post-discussion work': {
name: '7. Post-discussion work',
kind: StageKind.TakeSurvey,
questions: [
{
id: 0,
kind: SurveyQuestionKind.Rating,
questionText: 'Please rating the following accoring to which is best for survival',
item1: 'compas',
item2: 'blanket',
},
],
questions: RATING_QUESTION_CONFIGS,
},

'8. Leader reveal': {
Expand Down
1 change: 1 addition & 0 deletions utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export * from './types/votes.types';
export * from './utils/algebraic.utils';
export * from './utils/cache.utils';
export * from './utils/object.utils';
export * from './utils/random.utils';
export * from './utils/string.utils';

// Validation (peer dependency: @sinclair/typebox)
Expand Down
94 changes: 82 additions & 12 deletions utils/src/types/items.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,92 @@ export type ItemChoice = keyof ItemPair;
// ITEMS //
// ********************************************************************************************* //

export const ITEM_NAMES = ['blanket', 'compas', 'lighter'] as const;
export const ITEM_NAMES = [
'sextant',
'shavingMirror',
'mosquitoNetting',
'waterContainer',
'armyRations',
'pacificMaps',
'floatingSeatCushion',
'canOilMixture',
'transistorRadio',
'plasticSheeting',
'sharkRepellent',
'rubbingAlcohol',
'nylonRope',
'chocolateBars',
'fishingKit',
] as const;
export type ItemName = (typeof ITEM_NAMES)[number];
export const ITEMS: Record<ItemName, Item> = {
blanket: {
name: 'blanket',
sextant: {
name: 'Sextant',
imageUrl:
'https://img.freepik.com/free-psd/blanket-isolated-transparent-background_191095-10098.jpg?size=338&ext=jpg&ga=GA1.1.1700460183.1712448000&semt=sph',
'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Sextant_von_Alexander_von_Humboldt.jpg/640px-Sextant_von_Alexander_von_Humboldt.jpg',
},
compas: {
name: 'compas',
imageUrl: 'https://m.media-amazon.com/images/I/81NUeKWdiQL._AC_UF1000,1000_QL80_.jpg',
shavingMirror: {
name: 'Shaving mirror',
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/3/32/Mirror%2C_shaving_%28AM_880330-3%29.jpg',
},
mosquitoNetting: {
name: 'Mosquito netting',
imageUrl:
'https://commons.wikimedia.org/wiki/Category:Mosquito_nets#/media/File:Net,_mosquito_(AM_2015.20.7-1).jpg',
},
waterContainer: {
name: '25 liter container of Water',
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/c/c4/PikiWiki_Israel_65236_container_for_water.jpg',
},
armyRations: {
name: 'Case of Army Rations',
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/0/00/24_Hour_Multi_Climate_Ration_Pack_MOD_45157289.jpg',
},
pacificMaps: {
name: 'Maps of the Pacific Ocean', // ToDo - Change to Atlantic ocean?
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/d/d6/Kepler-world.jpg',
},
floatingSeatCushion: {
name: 'Floating Seat Cushion',
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/e/ec/EM_USAIRWAYS_EXPRESS_CRJ-200_%282878446162%29.jpg',
},
canOilMixture: {
name: '10 liter can of Oil/Petrol mixture',
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/3/33/Britische_copy_wehrmacht-einheitskanister_1943_jerrycan.jpg',
},
lighter: {
name: 'lighter',
transistorRadio: {
name: 'Small Transistor Radio',
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/White_lighter_with_flame.JPG/1200px-White_lighter_with_flame.JPG',
'https://upload.wikimedia.org/wikipedia/commons/b/b6/Vintage_Philco_6-Transistor_Radio%2C_Model_T76-124%2C_1958%2C_Leather_Case_%288385122630%29.jpg',
},
plasticSheeting: {
name: 'Plastic Sheeting',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/1/13/Film_StandardForm001.jpg',
},
sharkRepellent: {
name: 'Can of Shark Repellent',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/1/11/Konservendose-1.jpg',
},
rubbingAlcohol: {
name: 'One bottle rubbing alcohol',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/b/b7/Rubbing_alcohol.JPG',
},
nylonRope: {
name: '15 ft. of Nylon Rope',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/3/35/Nylon_Rope.JPG',
},
chocolateBars: {
name: '2 boxes of Chocolate Bars',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/9/91/2Tablettes_Grand_crus.png',
},
fishingKit: {
name: 'An ocean Fishing Kit & Pole',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/2/29/Fishing_time_at_sea.jpg',
},
};

Expand All @@ -42,7 +112,7 @@ export const ITEMS: Record<ItemName, Item> = {

export const getDefaultItemPair = (): ItemPair => {
return {
item1: 'blanket',
item2: 'compas',
item1: 'sextant',
item2: 'shavingMirror',
};
};
4 changes: 2 additions & 2 deletions utils/src/types/questions.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ export const getDefaultItemRatingsQuestion = (): RatingQuestionConfig => {
id: 0,
kind: SurveyQuestionKind.Rating,
questionText: '',
item1: 'blanket',
item2: 'compas',
item1: 'sextant',
item2: 'shavingMirror',
};
};

Expand Down
13 changes: 13 additions & 0 deletions utils/src/utils/object.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,16 @@ export const mergeableRecord = <K extends Index, V>(record: Record<K, V>, fieldN

return result;
};

/** Returns a list of all possible pairs of array elements without duplicates, assuming the array elements are distinct */
export const pairs = <T>(array: readonly T[]): [T, T][] => {
const result: [T, T][] = [];

for (let i = 0; i < array.length - 1; i++) {
for (let j = i + 1; j < array.length; j++) {
result.push([array[i], array[j]]);
}
}

return result;
};
55 changes: 55 additions & 0 deletions utils/src/utils/random.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/** Random utilities that support seeding. */

// ********************************************************************************************* //
// SEED //
// ********************************************************************************************* //

// Seed shared by all random functions.
let RANDOM_SEED = 0;

/** Initialize the seed with a custom value */
export const seed = (value: number) => {
RANDOM_SEED = value;
};

/** Update the seed using a Linear Congruential Generator */
const next = (a = 1664525, b = 1013904223, m = 2 ** 32) => {
RANDOM_SEED = (a * RANDOM_SEED + b) % m;
return RANDOM_SEED;
};

// ********************************************************************************************* //
// RANDOM FUNCTIONS //
// ********************************************************************************************* //

/** Returns a random floating point value in [0, 1] */
export const random = () => next() / 2 ** 32;

/** Returns a random integer in [min, max] */
export const randint = (min: number, max: number) => Math.floor(random() * (max - min + 1)) + min;

/** Chooses a random value from an array. The array is not modified. */
export const choice = <T>(array: readonly T[]): T => {
if (array.length === 0) {
throw new Error('Cannot choose from an empty array');
}

return array[randint(0, array.length - 1)];
};

/** Chooses n random distinct values from an array. The array is not modified. */
export const choices = <T>(array: readonly T[], n: number): T[] => {
if (array.length <= n) {
throw new Error(`Cannot choose ${n} distinct values from an array of length ${array.length}`);
}

const copy = [...array];
const result: T[] = [];
for (let i = 0; i < n; i++) {
const index = randint(0, copy.length - 1);
result.push(copy[index]);
copy.splice(index, 1);
}

return result;
};
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,21 @@
[disabled]="isSilent() || readyToEndChat()"
(change)="toggleEndChat()"
>
I'm done with chatting and ready to move on
@if (currentRatingsIndex() < stage.config().chatConfig.ratingsToDiscuss.length - 1) {
I'm done with chatting and ready to move on to the next pair of items
} @else {
I'm done with chatting and ready to move on to the next stage
}
</mat-slide-toggle>
</div>
</div>

@if (currentRatingsToDiscuss()) {
<b>Your discussion is now focusing on selecting the best item between the following items</b>
<b
>Your discussion is now focusing on selecting the best item between the following items ({{
currentRatingsIndex() + 1
}}/{{ stage.config().chatConfig.ratingsToDiscuss.length }})</b
>
<div class="flex-container">
<div class="item-pair-displays">
<div class="item-pair-item">
Expand Down

0 comments on commit 68c53c4

Please sign in to comment.