Pedagogical data exchange package for SuperApp Partner Applications
npm install @superapp_men/pedagogical-data-exchangeš Complete Guide to Pedagogical Data Exchange Package
1. Overview
2. Installation
3. Quick Start
4. Core Concepts
5. API Reference
6. Complete Examples
7. Validation & Remediation
8. Advanced Features
9. Best Practices
---
This package enables Partner Applications to submit detailed student assessment data to SuperApp in a secure, structured, and pedagogically consistent manner.
ā
Submit student test results and assessments
ā
Report partial or completed evaluations
ā
Support validation and remediation workflows
ā
Track learning progress and performance
ā
Provide rich analytics and insights
ā
Ensure compatibility with SuperApp's pedagogical model
Partner Applications submit facts, not decisions.
SuperApp retains full responsibility for:
- ā Skill validation
- ā Week unlocking
- ā Progression decisions
- ā Grade calculations
---
``bash`
npm install @superapp_men/pedagogical-data-exchange
Or with Yarn:
`bash`
yarn add @superapp_men/pedagogical-data-exchange
Or with PNPM:
`bash`
pnpm add @superapp_men/pedagogical-data-exchange
---
`typescript
import {
AssessmentSubmissionBuilder,
SkillResultBuilder,
QuestionResultBuilder,
SubmissionStatus,
QuestionType,
validateSubmission,
} from "@superapp_men/pedagogical-data-exchange";
// 1. Build a question
const question = new QuestionResultBuilder("MATH-Q1", QuestionType.VALIDATION)
.setResult(true)
.setAttempts(1)
.setAnsweredAt(new Date())
.setDuration(32)
.build();
// 2. Build a skill
const skill = new SkillResultBuilder("MATH-SK1")
.setStatus("Completed")
.addQuestion(question)
.build();
// 3. Build submission
const submission = new AssessmentSubmissionBuilder(
"STUDENT-ID",
SubmissionStatus.COMPLETED
)
.setProgressPercentage(100)
.setSourceApplication("MY_APP", "SESSION-ID")
.addSkill(skill)
.build();
// 4. Validate
const validation = validateSubmission(submission);
if (!validation.isValid) {
console.error("Errors:", validation.errors);
return;
}
// 5. Send to SuperApp
await sendToSuperApp(submission);
`
---
``
AssessmentSubmission
āāā Student ID (studentIID)
āāā Status (Partial/Completed/Abandoned)
āāā Progress (percentage, last question, counts)
āāā Skills[]
ā āāā Skill Code
ā āāā Skill Status (InProgress/Completed/Failed)
ā āāā Questions[]
ā āāā Question Code
ā āāā Question Type (Validation/Remediation)
ā āāā Result (true/false)
ā āāā Attempts Count
ā āāā Duration
ā āāā Answered At (timestamp)
āāā Performance Summary (auto-calculated)
āāā Pedagogical Insights (optional)
āāā Metadata (source, session, device)
| Status | When to Use |
| ------------- | --------------------------------------- |
| Partial | Student is still working; save progress |
| Completed | Student finished all questions |
| Abandoned | Student quit without finishing |
| Type | Purpose |
| --------------- | ---------------------------- |
| Validation | Test skill mastery |
| Remediation | Help after failed validation |
| Diagnostic | Assess starting level |
| Practice | Skill reinforcement |
---
Create a complete submission:
`typescript`
new AssessmentSubmissionBuilder(studentIID: string, status: SubmissionStatus)
Methods:
`typescript
// Progress
.setProgressPercentage(percentage: number)
.setLastAnsweredQuestion(questionCode: string)
// Source
.setSourceApplication(code: string, sessionId: string, deviceType?: string)
// Assessment
.setAssessment(code: string, name?: string, weekNumber?: number)
// Skills
.addSkill(skill: SkillResult)
.addSkills(skills: SkillResult[])
// Performance
.setPerformanceSummary(summary: PerformanceSummary)
.setPedagogicalInsights(insights: PedagogicalInsights)
// Build
.build(): AssessmentSubmission
`
Example:
`typescript`
const submission = new AssessmentSubmissionBuilder(
"STU-001",
SubmissionStatus.COMPLETED
)
.setProgressPercentage(100)
.setSourceApplication("PARTNER_APP", "SESSION-123", "Mobile")
.setAssessment("MATH-W3", "Week 3 Math", 3)
.addSkill(skill)
.build();
Create a skill with questions:
`typescript`
new SkillResultBuilder(skillCode: string)
Methods:
`typescript
// Status
.setStatus(status: 'InProgress' | 'Completed' | 'Failed')
.setName(name: string)
.setMasteryPercentage(percentage: number)
// Timing
.setTotalDuration(seconds: number)
.setStartedAt(timestamp: string | Date)
.setCompletedAt(timestamp: string | Date)
// Questions
.addQuestion(question: QuestionResult)
.addQuestions(questions: QuestionResult[])
// Build
.build(): SkillResult
`
Example:
`typescript`
const skill = new SkillResultBuilder("MATH-W3-SK1")
.setStatus("Completed")
.setName("Addition and Subtraction")
.setMasteryPercentage(95)
.addQuestion(question1)
.addQuestion(question2)
.build();
Create a question result:
`typescript`
new QuestionResultBuilder(questionCode: string, questionType: QuestionType)
Methods:
`typescript
// Core
.setResult(result: boolean)
.setAttempts(count: number)
.setAnsweredAt(timestamp: string | Date)
.setDuration(seconds: number)
// Remediation
.setTriggeredBy(questionCode: string, round?: number)
.setValidationPassedAfterRemediation(passed: boolean)
// Additional
.setDifficulty(level: DifficultyLevel)
.setPoints(earned: number, max: number)
// Build
.build(): QuestionResult
`
Example:
`typescript`
const question = new QuestionResultBuilder(
"MATH-W3-SK1-Q1",
QuestionType.VALIDATION
)
.setResult(true)
.setAttempts(1)
.setAnsweredAt(new Date())
.setDuration(32)
.build();
#### SubmissionHelpers
`typescript
// Quick validation question
SubmissionHelpers.createValidationQuestion(
code: string,
result: boolean,
attempts?: number,
duration?: number
): QuestionResult
// Quick remediation question
SubmissionHelpers.createRemediationQuestion(
code: string,
triggeredBy: string,
result: boolean,
round?: number,
duration?: number
): QuestionResult
// Auto-calculate performance
SubmissionHelpers.calculatePerformanceSummary(
skills: SkillResult[]
): PerformanceSummary
// Auto-calculate progress
SubmissionHelpers.calculateProgress(
skills: SkillResult[],
totalExpectedQuestions?: number
): ProgressTracking
`
Examples:
`typescript
// Create validation question quickly
const q1 = SubmissionHelpers.createValidationQuestion("Q1", true, 1, 30);
// Create remediation question quickly
const r1 = SubmissionHelpers.createRemediationQuestion(
"Q1-R1",
"Q1",
true,
1,
40
);
// Auto-calculate performance
const performance = SubmissionHelpers.calculatePerformanceSummary(skills);
// Auto-calculate progress
const progress = SubmissionHelpers.calculateProgress(skills, 20);
`
`typescript`
validateSubmission(submission: AssessmentSubmission): ValidationResult
Returns:
`typescript`
{
isValid: boolean;
errors: ValidationError[];
warnings: ValidationWarning[];
}
Example:
`typescript
const result = validateSubmission(submission);
if (!result.isValid) {
console.error("Validation failed!");
result.errors.forEach((error) => {
console.error([${error.code}] ${error.message});
});
return;
}
console.log("ā
Validation passed!");
`
`typescript
import { PedagogicalUtils } from '@superapp_men/pedagogical-data-exchange';
// Calculate metrics
PedagogicalUtils.calculateAccuracy(skills): number
PedagogicalUtils.calculateSkillCompletionRate(skills): number
PedagogicalUtils.calculateTotalTimeSpent(skills): number
// Get questions
PedagogicalUtils.getValidationQuestions(skills): QuestionResult[]
PedagogicalUtils.getRemediationQuestions(skills): QuestionResult[]
// Analysis
PedagogicalUtils.generateSummary(submission): SummaryObject
PedagogicalUtils.exportToCSV(submission): string
PedagogicalUtils.formatDuration(seconds): string
`
---
`typescript
import {
AssessmentSubmissionBuilder,
SkillResultBuilder,
SubmissionHelpers,
SubmissionStatus,
DeviceType,
} from "@superapp_men/pedagogical-data-exchange";
// Build skill with 5 questions
const skill = new SkillResultBuilder("MATH-W1-SK1")
.setStatus("Completed")
.setName("Basic Addition")
.addQuestions([
SubmissionHelpers.createValidationQuestion("Q1", true, 1, 20),
SubmissionHelpers.createValidationQuestion("Q2", true, 1, 25),
SubmissionHelpers.createValidationQuestion("Q3", true, 1, 18),
SubmissionHelpers.createValidationQuestion("Q4", true, 1, 22),
SubmissionHelpers.createValidationQuestion("Q5", true, 1, 30),
])
.build();
// Build submission
const submission = new AssessmentSubmissionBuilder(
"STU-001",
SubmissionStatus.COMPLETED
)
.setProgressPercentage(100)
.setSourceApplication("PARTNER_APP", "SESSION-001", DeviceType.TABLET)
.setAssessment("MATH-W1", "Week 1 Assessment", 1)
.addSkill(skill)
.build();
// Validate and send
const validation = validateSubmission(submission);
if (validation.isValid) {
await sendToSuperApp(submission);
}
`
`typescript
// Student completed 1 skill, partially completed another
const skill1 = new SkillResultBuilder("MATH-W2-SK1")
.setStatus("Completed")
.addQuestions([
SubmissionHelpers.createValidationQuestion("SK1-Q1", true, 1, 30),
SubmissionHelpers.createValidationQuestion("SK1-Q2", true, 1, 35),
])
.build();
const skill2 = new SkillResultBuilder("MATH-W2-SK2")
.setStatus("InProgress")
.addQuestions([
SubmissionHelpers.createValidationQuestion("SK2-Q1", true, 1, 40),
// Student stopped here
])
.build();
const submission = new AssessmentSubmissionBuilder(
"STU-002",
SubmissionStatus.PARTIAL
)
.setProgressPercentage(50)
.setLastAnsweredQuestion("SK2-Q1")
.setSourceApplication("PARTNER_APP", "SESSION-002")
.addSkills([skill1, skill2])
.build();
await sendToSuperApp(submission);
`
`typescript
import {
QuestionResultBuilder,
QuestionType,
} from "@superapp_men/pedagogical-data-exchange";
// Complete remediation flow
const questions = [
// 1. Failed validation
new QuestionResultBuilder("MATH-Q1", QuestionType.VALIDATION)
.setResult(false)
.setAttempts(2)
.setAnsweredAt("2026-01-08T10:20:03Z")
.setDuration(51)
.build(),
// 2. Remediation
new QuestionResultBuilder("MATH-Q1-R1", QuestionType.REMEDIATION)
.setResult(true)
.setAttempts(1)
.setAnsweredAt("2026-01-08T10:22:40Z")
.setDuration(40)
.setTriggeredBy("MATH-Q1", 1)
.build(),
// 3. Retry validation (success!)
new QuestionResultBuilder("MATH-Q1", QuestionType.VALIDATION)
.setResult(true)
.setAttempts(3)
.setAnsweredAt("2026-01-08T10:24:05Z")
.setDuration(36)
.setValidationPassedAfterRemediation(true)
.build(),
];
const skill = new SkillResultBuilder("MATH-SK1")
.setStatus("Completed")
.addQuestions(questions)
.build();
`
`typescript
import { SubmissionHelpers } from "@superapp_men/pedagogical-data-exchange";
// Build skills
const skills = [skill1, skill2, skill3];
// Auto-calculate performance
const performance = SubmissionHelpers.calculatePerformanceSummary(skills);
// Build submission with performance
const submission = new AssessmentSubmissionBuilder(
"STU-003",
SubmissionStatus.COMPLETED
)
.setProgressPercentage(100)
.setSourceApplication("PARTNER_APP", "SESSION-003")
.setPerformanceSummary(performance)
.addSkills(skills)
.build();
await sendToSuperApp(submission);
`
---
``
1. Validation Question (Test)
ā
Pass or Fail?
ā
āāāāāāā“āāāāāā
ā ā
Pass Fail
ā ā
ā ā
ā 2. Remediation
ā (Learn)
ā ā
ā 3. Retry Validation
ā ā
āāāāāāāāāāāāā“āāā Skill Complete
`typescript
// Step 1: Failed validation
const failedValidation = new QuestionResultBuilder(
"MATH-W3-SK2-Q1",
QuestionType.VALIDATION
)
.setResult(false)
.setAttempts(2)
.setAnsweredAt("2026-01-08T10:20:03Z")
.setDuration(51)
.build();
// Step 2: Remediation
const remediation = new QuestionResultBuilder(
"MATH-W3-SK2-Q1-R1",
QuestionType.REMEDIATION
)
.setResult(true)
.setAttempts(1)
.setAnsweredAt("2026-01-08T10:22:40Z")
.setDuration(40)
.setTriggeredBy("MATH-W3-SK2-Q1", 1)
.build();
// Step 3: Successful retry
const successfulRetry = new QuestionResultBuilder(
"MATH-W3-SK2-Q1",
QuestionType.VALIDATION
)
.setResult(true)
.setAttempts(3)
.setAnsweredAt("2026-01-08T10:24:05Z")
.setDuration(36)
.setValidationPassedAfterRemediation(true)
.build();
// Add all to skill
const skill = new SkillResultBuilder("MATH-W3-SK2")
.setStatus("Completed")
.addQuestion(failedValidation)
.addQuestion(remediation)
.addQuestion(successfulRetry)
.build();
`
---
`typescript
import { PedagogicalUtils } from "@superapp_men/pedagogical-data-exchange";
// Calculate metrics
const accuracy = PedagogicalUtils.calculateAccuracy(skills);
const completionRate = PedagogicalUtils.calculateSkillCompletionRate(skills);
const avgAttempts = PedagogicalUtils.calculateAverageAttempts(skills);
const totalTime = PedagogicalUtils.calculateTotalTimeSpent(skills);
console.log(
Accuracy: ${accuracy.toFixed(1)}%
Completion: ${completionRate.toFixed(1)}%
Avg Attempts: ${avgAttempts.toFixed(2)}
Total Time: ${PedagogicalUtils.formatDuration(totalTime)});`
`typescript
const summary = PedagogicalUtils.generateSummary(submission);
console.log(summary);
// {
// studentId: 'STU-123',
// totalSkills: 3,
// completedSkills: 2,
// totalQuestions: 15,
// correctAnswers: 12,
// accuracy: 80,
// totalTime: 840,
// averageAttempts: 1.5,
// remediationRate: 100
// }
`
`typescript
const csv = PedagogicalUtils.exportToCSV(submission);
// Save or send to server
fs.writeFileSync("results.csv", csv);
`
`typescript
// Create batch for multiple students
const submissions = [
createSubmissionForStudent("STU-001"),
createSubmissionForStudent("STU-002"),
createSubmissionForStudent("STU-003"),
];
const batch = PedagogicalUtils.createBatchSubmission(
submissions,
"PARTNER_APP"
);
await sendBatchToSuperApp(batch);
`
---
`typescript`
const validation = validateSubmission(submission);
if (!validation.isValid) {
logErrors(validation.errors);
return;
}
`typescript
// ā
Good
const question = new QuestionResultBuilder("Q1", QuestionType.VALIDATION)
.setResult(true)
.build();
// ā Bad
const question = {
questionCode: "Q1",
questionType: "Validation",
result: true,
};
`
`typescript
// ā
Good
.setAnsweredAt(new Date().toISOString())
.setAnsweredAt('2026-01-08T10:15:22Z')
// ā Bad
.setAnsweredAt('01/08/2026 10:15 AM')
`
`typescript
const startTime = Date.now();
// Student answers...
const duration = Math.round((Date.now() - startTime) / 1000);
questionBuilder.setDuration(duration);
`
`typescript`
// Quick question creation
const q = SubmissionHelpers.createValidationQuestion("Q1", true, 1, 30);
`typescript`
const performance = SubmissionHelpers.calculatePerformanceSummary(skills);
builder.setPerformanceSummary(performance);
`typescript
// Save progress when student pauses
if (studentPaused) {
const partial = builder
.setProgressPercentage(currentProgress)
.setLastAnsweredQuestion(lastQuestionCode)
.build();
await sendToSuperApp(partial);
}
`
`typescript`
remediationBuilder.setTriggeredBy("VALIDATION-Q-CODE", roundNumber).build();
---
Partner Apps should submit facts, not decisions:
- Skill validation decisions
- Week unlocking logic
- Progression decisions
- Final grades
- Next skill recommendations
- Raw results (true/false)
- Attempt counts
- Time spent
- Answer details
- Interaction data
SuperApp decides everything pedagogical.
---
Full TypeScript support:
`typescript`
import type {
AssessmentSubmission,
SkillResult,
QuestionResult,
SubmissionStatus,
QuestionType,
ValidationResult,
SubmissionResponse,
} from "@superapp_men/pedagogical-data-exchange";
---
The validator checks:
ā
Required fields presence
ā
Correct data types
ā
Value ranges (0-100 for percentages)
ā
Logical consistency
ā
Remediation flow correctness
ā
ISO 8601 timestamps
ā
No duplicates
---
After submission:
`typescript
{
submissionId: string;
accepted: boolean;
processedAt: string;
validation: {
isValid: boolean;
errors?: ValidationError[];
};
processingResults?: {
validatedSkills?: string[];
unlockedSkills?: string[];
weekProgression?: { ... };
achievementsEarned?: string[];
pointsEarned?: number;
};
recommendations?: {
nextSkills?: string[];
remediationRequired?: string[];
};
}
`
`typescript
const response = await sendToSuperApp(submission);
if (response.accepted) {
console.log("ā
Accepted!");
if (response.processingResults?.weekProgression?.weekUnlocked) {
showNotification("New week unlocked!");
}
if (response.processingResults?.achievementsEarned) {
showAchievements(response.processingResults.achievementsEarned);
}
}
``
---
- Email: h.afifi@alexsys.solutions
---
MIT
---
Ready to integrate? Install and start submitting! šāØ