Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
214ad7b
first commit
clebouleau Oct 28, 2025
b119d2e
second commit
clebouleau Oct 28, 2025
44464db
changin link to image folder
clebouleau Oct 28, 2025
fc56d45
changin link to image folder
clebouleau Oct 28, 2025
5cca7e4
starting new selection logic
clebouleau Oct 28, 2025
6177801
starting new selection logic 2
clebouleau Oct 28, 2025
f972a8d
starting new selection logic 3
clebouleau Oct 29, 2025
3019be8
starting new selection logic 3
clebouleau Oct 29, 2025
de581c6
starting new selection logic 3
clebouleau Oct 29, 2025
1d73017
starting new selection logic 3
clebouleau Oct 29, 2025
eeb37bd
progress chris and clem in Paris
clebouleau Nov 10, 2025
c61c654
progress chris and clem in Paris - debug new changes
clebouleau Nov 10, 2025
1c0835d
progress clem
clebouleau Nov 11, 2025
db9a3e4
clem 2
clebouleau Nov 11, 2025
3c7b5bf
clem 2
clebouleau Nov 11, 2025
d581a84
ajout createLRRankingStagePublicData
clebouleau Nov 12, 2025
be7637e
la page de feedback 1 s'affiche (mais pas avec le bon feedback)
clebouleau Nov 12, 2025
293061e
debug de la procédure de ranking intial qui marchait plus
clebouleau Nov 13, 2025
1e9f7bb
debug de la procédure de ranking intial qui marchait plus
clebouleau Nov 14, 2025
bebfd14
debug de la procédure de ranking intial qui marchait plus
clebouleau Nov 19, 2025
da1b34b
m
clebouleau Nov 19, 2025
70564f1
debugging score calculations
clebouleau Nov 19, 2025
2517f0d
updating full LR template
clebouleau Nov 20, 2025
724a80a
Fixed LR experiment export problem
CBirch16 Nov 23, 2025
8e72519
Simplified LR Ranking Stage (only text + button next)
CBirch16 Nov 24, 2025
28b9a32
adjusting disable button in LR ranking case
clebouleau Nov 24, 2025
d8056a9
display status + group leader ID
clebouleau Nov 24, 2025
7dee7db
adjusting template
clebouleau Nov 24, 2025
a48cd4b
fixed compil warnings in algebraic.utils.ts
CBirch16 Nov 24, 2025
3620dbe
Merge remote-tracking branch 'upstream/main' into leader-rejection
CBirch16 Nov 26, 2025
86d9814
Reported last leader_rejection_template.ts update (from main branch)
CBirch16 Nov 27, 2025
ea14302
adjusting template - changing to consol logs
clebouleau Nov 28, 2025
3eed571
Removed idea files
CBirch16 Nov 28, 2025
ad35be9
Removed package-lock.json
CBirch16 Nov 28, 2025
16fe8ff
restored package-lock.json
CBirch16 Nov 28, 2025
3e07517
Merge branch 'main' into leader-rejection
CBirch16 Dec 13, 2025
5917364
fixed previous merge typo error
CBirch16 Dec 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ node_modules/
# Packed shared utils package
*deliberation-lab-utils-*.tgz

.idea/

# Python scripts
.venv
*.pyc
Expand Down
Binary file added frontend/assets/survival_desert/aid.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/survival_desert/book.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/survival_desert/flashlight.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/survival_desert/knife.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/survival_desert/mirror.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/survival_desert/parachute.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/survival_desert/pistol.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/survival_desert/raincoat.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/survival_desert/salt.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file added frontend/assets/survival_desert/water.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
133 changes: 71 additions & 62 deletions frontend/index.example.html
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to edit this file?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jimbojw , no I think this was an unintended IDE auto-formatting change

Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
<html>

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Deliberate Lab</title>
<link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=block" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" />
<% if (process.env.NODE_ENV==='production' ) { %>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Deliberate Lab</title>
<link
href="https://fonts.googleapis.com/css?family=Material+Icons&display=block"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=block"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
/>
<% if (process.env.NODE_ENV==='production' ) { %>
<script>
function addAnalyticsScript() {
// Create a new script element
Expand Down Expand Up @@ -38,59 +48,58 @@
addAnalyticsScript();
</script>
<% } %>
<style>
body {
margin: 0;
}

.noscript {
align-items: center;
background: #eee;
box-sizing: border-box;
color: #222;
display: flex;
flex-direction: column;
font-family: 'Inter', Helvetica, sans-serif;
font-size: 16px;
height: 100%;
line-height: 22px;
margin: 0;
padding: 24px;
}
<style>
body {
margin: 0;
}

.noscript section {
background: #fff;
border-radius: 8px;
color: #222;
display: flex;
flex-direction: column;
gap: 8px;
padding: 16px;
}
.noscript {
align-items: center;
background: #eee;
box-sizing: border-box;
color: #222;
display: flex;
flex-direction: column;
font-family: 'Inter', Helvetica, sans-serif;
font-size: 16px;
height: 100%;
line-height: 22px;
margin: 0;
padding: 24px;
}

.noscript h1 {
font-size: 22px;
font-weight: 500;
line-height: 28px;
margin: 0;
}
.noscript section {
background: #fff;
border-radius: 8px;
color: #222;
display: flex;
flex-direction: column;
gap: 8px;
padding: 16px;
}

.noscript p {
margin: 0;
}
</style>
</head>
.noscript h1 {
font-size: 22px;
font-weight: 500;
line-height: 28px;
margin: 0;
}

<body>
<noscript class="noscript">
<section>
<h1>🕊️ JavaScript required</h1>
<p>
Welcome to Deliberate Lab! You'll need to enable JavaScript
to use this app.
</p>
</section>
</noscript>
</body>
.noscript p {
margin: 0;
}
</style>
</head>

</html>
<body>
<noscript class="noscript">
<section>
<h1>🕊️ JavaScript required</h1>
<p>
Welcome to Deliberate Lab! You'll need to enable JavaScript to use
this app.
</p>
</section>
</noscript>
</body>
</html>
46 changes: 43 additions & 3 deletions frontend/src/components/experiment_builder/stage_builder_dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
createAssetAllocationStage,
createChatStage,
createRankingStage,
createLRRankingStage,
createInfoStage,
createFlipCardStage,
createMultiAssetAllocationStage,
Expand All @@ -41,6 +42,10 @@ import {
getLASStageConfigs,
getAnonLASStageConfigs,
} from '../../shared/templates/lost_at_sea';
import {
LR_METADATA,
getLeadershipRejectionStageConfigs,
} from '../../shared/templates/leader_rejection_template';
import {
getChipMetadata,
getChipNegotiationStageConfigs,
Expand Down Expand Up @@ -173,7 +178,7 @@ export class StageBuilderDialog extends MobxLitElement {
configuration!
</div>
<div class="card-gallery-wrapper">
${this.renderFlipCardTemplateCard()}
${this.renderLRCard()} ${this.renderFlipCardTemplateCard()}
${this.renderFruitTestTemplateCard()}
${this.renderConditionalSurveyTemplateCard()}
${this.renderStockInfoGameCard()}
Expand Down Expand Up @@ -242,8 +247,8 @@ export class StageBuilderDialog extends MobxLitElement {
${this.renderTransferCard()} ${this.renderSurveyCard()}
${this.renderSurveyPerParticipantCard()}
${this.renderComprehensionCard()} ${this.renderRankingCard()}
${this.renderRevealCard()} ${this.renderPayoutCard()}
${this.renderRoleCard()}
${this.renderLRRankingCard()} ${this.renderRevealCard()}
${this.renderPayoutCard()} ${this.renderRoleCard()}
</div>
</div>

Expand Down Expand Up @@ -301,6 +306,25 @@ export class StageBuilderDialog extends MobxLitElement {
`;
}

private renderLRCard() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and elsewhere, it won't be immediately clear to the reader of the code that "LR" means "Leader Rejection". Recommend spelling it out everywhere. (The renderLRRankingCard() method below, createLRRankingStage(), LRRankingStagePublicData, etc.)

const metadata = LR_METADATA;
const configs = getLeadershipRejectionStageConfigs();

const addGame = () => {
this.addGame(metadata, configs);
};

return html`
<div class="card" @click=${addGame}>
<div class="title">${metadata.name}</div>
<div>
${metadata.description}
<div></div>
</div>
</div>
`;
}

private renderAgentIntegrationCard() {
const addTemplate = () => {
this.addTemplate(getAgentParticipantIntegrationTemplate());
Expand Down Expand Up @@ -508,6 +532,22 @@ export class StageBuilderDialog extends MobxLitElement {
`;
}

private renderLRRankingCard() {
const addStage = () => {
this.addStage(createLRRankingStage());
};

return html`
<div class="card" @click=${addStage}>
<div class="title">🗳️ LR Triggering Selection Logic</div>
<div>
TODO: Stage that triggers the selection of a leader based on candidacy
and performance in two initial tasks
</div>
</div>
`;
}

private renderRevealCard() {
const addStage = () => {
this.addStage(createRevealStage());
Expand Down
88 changes: 88 additions & 0 deletions frontend/src/components/stages/leader_status_reveal_view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import '../participant_profile/profile_display';

import {MobxLitElement} from '@adobe/lit-mobx';
import {CSSResultGroup, html, nothing} from 'lit';
import {customElement, property} from 'lit/decorators.js';

import {LRRankingStagePublicData} from '@deliberation-lab/utils';
import {core} from '../../core/core';
import {ParticipantService} from '../../services/participant.service';
import {styles} from './ranking_reveal_view.scss';
import {getParticipantInlineDisplay} from '../../shared/participant.utils';

import {CohortService} from '../../services/cohort.service';

/** Leader selection reveal view */
@customElement('leader-reveal-view')
export class LeaderRevealView extends MobxLitElement {
static override styles: CSSResultGroup = [styles];

private readonly participantService = core.getService(ParticipantService);
private readonly cohortService = core.getService(CohortService);

@property() publicData: LRRankingStagePublicData | undefined = undefined;

override render() {
if (!this.publicData) return html`<p><em>Waiting for results...</em></p>`;

const leaderStatusMap = this.publicData.leaderStatusMap || {};
const winnerId = this.publicData.winnerId || '';
const participantId = this.participantService.profile?.publicId ?? ''; // ✅ FIXED
const status = leaderStatusMap[participantId] ?? 'waiting';

const messages: Record<string, string> = {
candidate_accepted: '✅ You applied and were selected as leader!',
candidate_rejected: '❌ You applied but were not selected.',
non_candidate_accepted:
'✅ You did not apply, but since no one else did, you were selected!',
non_candidate_rejected: '❌ You did not apply and were not selected.',
non_candidate_hypo_selected:
'💡 You did not apply, but had you done so, you would have been selected.',
non_candidate_hypo_rejected:
'ℹ️ You did not apply, and even if you had, you would not have been selected.',
waiting: '⏳ Waiting for results...',
};

// 🔍 Determine whether to show who the leader is
const showWinner =
winnerId && participantId !== winnerId && status !== 'waiting';

// 🔍 Convert winnerId → "Participant 7506"
let winnerPretty: string | null = null;
if (showWinner) {
const winnerProfile = this.cohortService.participantMap?.[winnerId];
if (winnerProfile) {
winnerPretty = getParticipantInlineDisplay(winnerProfile); // 👈 magic happens here
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What magic happens?

} else {
winnerPretty = winnerId; // fallback (should rarely happen)
}
}

console.log('[LeaderRevealView] my ID:', participantId);
console.log('[LeaderRevealView] all keys:', Object.keys(leaderStatusMap));
console.log(
'[LeaderRevealView] publicData snapshot:',
JSON.parse(JSON.stringify(this.publicData)),
);

return html`
<div class="leader-status-block">
<h3>Leader Selection Result</h3>
<p>${messages[status] ?? messages.waiting}</p>
${showWinner && winnerPretty
? html`
<p style="margin-top: 12px; font-size: 0.95em; opacity: 0.8;">
<strong>${winnerPretty}</strong> was selected as the leader.
</p>
`
: nothing}
</div>
`;
}
}

declare global {
interface HTMLElementTagNameMap {
'leader-reveal-view': LeaderRevealView;
}
}
44 changes: 44 additions & 0 deletions frontend/src/components/stages/lr_info_ranking_view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {MobxLitElement} from '@adobe/lit-mobx';
import {html, nothing} from 'lit';
import {customElement, property} from 'lit/decorators.js';

import {core} from '../../core/core';
import {ParticipantService} from '../../services/participant.service';
import {RankingStageConfig} from '@deliberation-lab/utils';

@customElement('lr-info-ranking-view')
export class LRInfoRankingView extends MobxLitElement {
@property() stage!: RankingStageConfig;

private readonly participantService = core.getService(ParticipantService);

override render() {
if (!this.stage) return nothing;

return html`
<div class="lr-info-wrapper">
<h3>${this.stage.name}</h3>
<p>This is an information-only page. No ranking is required.</p>

<button @click=${this.next}>Next</button>
</div>
`;
}

private async next() {
// Submit empty ranking list → triggers LR logic
const ps = this.participantService;
await ps.updateRankingStageParticipantAnswer(
this.stage.id,
[], // very important!
);

await ps.progressToNextStage();
}
}

declare global {
interface HTMLElementTagNameMap {
'lr-info-ranking-view': LRInfoRankingView;
}
}
5 changes: 3 additions & 2 deletions frontend/src/components/stages/payout_summary_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,9 @@ export class PayoutView extends MobxLitElement {
<div class="row">
<div>
${rankingWinner !== null
? `Election winner's answer:`
: 'Your answer:'}
? `Leader's answer:`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it would affect experiments other than Leader Rejection.

: //? `Election winner's answer:`
'Your answer:'}
</div>
<div class="chip secondary">${participantAnswer?.text ?? ''}</div>
</div>
Expand Down
Loading