Yhdistä Puzzel omaan alustaasi
Puzzel voi antaa pelaajan tuloksen suoraan toiselle järjestelmälle — pistemäärän, etenemisen, vastatut kysymykset — ilman että kyseisen järjestelmän tarvitsee olla täysi LMS. Tämä sivu käy läpi jokaisen kanavan: mitä lähtee ulos, milloin se lähtee, ja pienimmän asian, joka sinun täytyy rakentaa sen vastaanottamiseksi.
- Tulokset lähtevät
- Webhookin kautta, tai viestinä aktiviteettia ympäröivälle sivulle
- Sivusi voi
- Kirjata pelaajan sisään ja nollata aktiviteetin
- Otetaan käyttöön
- Aktiviteettikohtaisesti, editorin Kehittäjä-valikossa
- Sisältyy
- Maksulliseen pakettiin — nämä asetukset ovat pois päältä ilmaisella tilillä
Minkä kanavan tarvitset?
Kolme asiaa voi lähteä aktiviteetista ulos ja yksi voi tulla sisään. Kumpi sopii, riippuu yhdestä kysymyksestä: istuuko pelaaja sinun sivullasi vai jossain aivan muualla?
Jokainen tallennettu tulos lähetetään POST-pyynnöllä omistamaasi URL-osoitteeseen JSON-muodossa.
- Käytä tätä, kun
- Pelaaja voi olla missä tahansa — jaetussa linkissä, QR-koodissa, jonkun toisen sivustolla — ja haluat tuloksen omaan tietokantaasi.
- Tarvitset
- HTTPS-päätepisteen, joka hyväksyy cross-origin-POST-pyynnön.
save_puzzle_results_via_webhookSama JSON, lähetettynä aktiviteetin upottavalle sivulle palvelimen sijaan.
- Käytä tätä, kun
- Upotat aktiviteetin omalle kurssisivullesi ja sivu itse voi tehdä jotain tuloksella.
- Tarvitset
- Iframen sivullasi ja viestikuuntelijan. Ei palvelinta, ei CORSia.
save_results_iframe_postmessageYksi viesti, kun pelaaja lopettaa, eikä se sisällä muuta kuin tämän tiedon.
- Käytä tätä, kun
- Haluat tietää vain, onko pelaaja valmis — merkitäksesi oppitunnin suoritetuksi, avataksesi seuraavan tai näyttääksesi oman näkymäsi.
- Tarvitset
- Iframen sivullasi ja viestikuuntelijan.
send_completion_signal_when_embeddedTulosten webhook
Kytke editorissa päälle "Lähetä tulokset webhookiin" ja anna sille URL-osoite. Siitä lähtien pelaajan selain lähettää koko tuloksen POST-pyynnöllä kyseiseen osoitteeseen JSON-muodossa aina, kun pelaajan eteneminen tallennetaan.
- 1 Avaa aktiviteetti editorissa ja siirry Kehittäjä-valikkoon.
- 2 Kytke päälle "Lähetä tulokset webhookiin" ja liitä päätepisteesi sen alla olevaan kenttään. Sen täytyy olla täydellinen URL-osoite — pelkkä verkkotunnus hylätään — ja sen täytyy olla https, koska selain estää tavallisen http-kutsun sivulta, joka on tarjottu https:n kautta.
- 3 Pelaa aktiviteettia itse kerran. Ensimmäinen POST-pyyntö saapuu heti, kun vastaat johonkin.
import express from 'express';
const app = express();
// The POST is made by the player's browser, so the browser asks permission
// first. Answer the preflight and the real request can land.
app.use((req, res, next) => {
res.set('Access-Control-Allow-Origin', 'https://puzzel.org');
res.set('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') return res.sendStatus(204);
next();
});
app.post('/puzzel/results', express.json(), async (req, res) => {
const result = req.body;
// One run posts several times as it goes. Key on the pair, not on an
// insert: each call carries the whole state, so the newest simply wins.
await db.results.upsert(
{ playerUid: result.playerUid, activityKey: result.activityKey },
result
);
// Only act on the finish once.
if (result.progress >= 100 || result.hasAlternateCompletion) {
await markCourseStepComplete(result);
}
res.sendStatus(200);
});Tulos lähtee ulos aina, kun merkintä tallennetaan: kirjoittamisen tauon jälkeen, kun kortti asetetaan paikalleen, kun kello pysähtyy, ja vielä kerran, kun aktiviteetti on valmis. Pitkässä sanaristikossa kutsuja kertyy pari kymmentä, ei yhtä — kirjoita siis käsittelijäsi upsertiksi, jonka avaimena on playerUid ja activityKey, älä lisäykseksi. Jokainen kutsu kantaa mukanaan koko tilan, joten uusin korvaa aina edellisen, ja kadonneen kutsun korjaa seuraava.
progress on prosenttiluku: 100 tarkoittaa, että aktiviteetti on valmis. Muutama tyyppi voi päättyä saavuttamatta sitä — kokonaan vastattu Quiz, ratkaistu ratkaisukenttä — ja niissä on sen sijaan hasAlternateCompletion. Kohtele kumpaakin valmiina.
POST-pyyntö tulee välilehdeltä, jolla aktiviteettia pelataan, ei Puzzelin palvelimelta. Useimmat webhookeja vastaanottamaan rakennetut päätepisteet hyväksyvät sen jo valmiiksi. Jos omasi ei koskaan näe pyyntöä, tämä on syy: selain kysyy luvan ensin, joten vastaa OPTIONS-esitarkistukseen Access-Control-Allow-Origin-otsakkeella, niin varsinainen POST seuraa perässä.
Pyynnössä ei ole allekirjoitusta, ja se tulee selaimesta, jota et hallitse, joten kuka tahansa sivua katsova voi lähettää sinulle samanlaisen. Se riittää edistymispalkkiin tai hallintapaneeliin. Kaikkea, mitä et antaisi oppilaan itse asettaa — laskettavaa arvosanaa, todistusta, maksua — varten tarkista se omasta Puzzel-hallintapaneelistasi löytyviä tuloksia vasten, tai anna pistemäärän kulkea sen sijaan LMS-arvosanaliitäntöjen kautta.
Tulokset sen ympäröivälle sivulle
Jos upotat aktiviteetin, voit lähettää saman JSON:n omalle sivullesi palvelimen sijaan. Kytke päälle "Lähetä tulokset upottavalle sivulle" ja kuuntele viestiä. Mikään ei poistu selaimesta, joten päätepistettä ei tarvitse rakentaa eikä CORSia tarvitse miettiä.
<iframe
src="https://puzzel.org/en/quiz/embed?p=-Nq8sample_activity_key"
width="100%"
height="700"
frameborder="0"
allowfullscreen
></iframe>
<script>
window.addEventListener('message', (event) => {
if (event.origin !== 'https://puzzel.org') return;
const result = event.data;
if (!result || !result.activityKey) return;
// Same shape the webhook posts, same advice: it arrives repeatedly.
saveProgress(result);
});
</script>Kuuntelijasi kuulee jokaisen sivulle lähetetyn viestin, myös muilta kehyksiltä ja selainlaajennuksilta. Vertaa event.origin-arvoa osoitteeseen https://puzzel.org ennen kuin luotat sen sisältöön.
Tämä on webhookin kaksoisolento: samat kentät, lähetettynä samoina hetkinä. Kaikki kohdassa "Mitä tulos sisältää" pätee myös tähän.
Valmistumissignaali
Pienin kanava, kun itse tulos ei kuulu sinulle: kytke päälle "Lähetä valmistumissignaali", ja sivusi saa yhden viestin heti, kun pelaaja lopettaa.
window.addEventListener('message', (event) => {
if (event.origin !== 'https://puzzel.org') return;
if (event.data?.completed !== true) return;
// { completed: true, activityKey: '-Nq8sample_activity_key' }
unlockNextLesson(event.data.activityKey);
});{
"completed": true,
"activityKey": "-Nq8sample_activity_key"
}Signaali lähetetään tarkoituksella vasta, kun valmistumiseen johtanut tallennus on tehty, joten sivu, joka reagoi lukemalla tuloksen takaisin, löytää sen jo sieltä.
Molemmat viestikanavat lähettävät viestin sivulle, joka kehystää aktiviteetin. Omalla välilehdellä avattuna kellekään ei ole ketä kertoa, joten mitään ei lähetetä.
Mitä tulos sisältää
Yksi muoto, kanavasta riippumatta. Pelaajan vastausten avaimina toimivat aktiviteetin omat kohdetunnisteet, joten samat avaimet löytyvät myös kohteesta correctUids.
| Kenttä | Tyyppi | Mitä se tekee |
|---|---|---|
activityKey aina string | string | Aktiviteetti, johon tulos kuuluu. Sama avain, jonka näet aktiviteetin omassa URL-osoitteessa, kohdan ?p= jälkeen. |
playerUid aina string | string | Kuka pelasi, anonyyminä tunnisteena. Pysyy samana tälle pelaajalle tällä laitteella, joten juuri sen mukaan tulokset kannattaa ryhmitellä — se ei ole sähköpostiosoite eikä Puzzel-tili. |
player joskus object | object | Rekisteröitymiskentät, joita aktiviteetti kysyy, sellaisina kuin määritit ne: nimi, sähköposti, luokka, student_id ja niin edelleen. Puuttuu, kunnes pelaaja on rekisteröitynyt, ja puuttuu kokonaan aktiviteetista, joka ei kysy mitään. |
progress aina number | number | Kuinka pitkälle on edetty, prosentteina. 100 tarkoittaa valmista. |
timePassed aina number | number | Aktiviteetissa käytetty aika, millisekunteina. |
lastPlayedAt aina number | number | Milloin tämä tulos tallennettiin, Unix-aikaleimana millisekunteina. |
createdAt joskus number | number | Milloin yritys aloitettiin, Unix-aikaleimana millisekunteina. |
playerInput joskus object | object | Mitä pelaaja todella syötti, ryhmiteltynä sen kohteen tunnisteen mukaan, johon syöte kuuluu. Sisällön muoto riippuu aktiviteettityypistä — sana, sijoitettujen korttien luettelo, valittu vaihtoehto. |
correctUids joskus object | object | Mitkä näistä kohteista ovat oikein, ryhmiteltynä samalla tavalla. Puuttuu, kun mihinkään ei ole vielä vastattu. |
score joskus number | number | Saadut pisteet, tyypeillä, jotka pisteyttävät pelikerran. Puuttuu kaikkialla muualla — myös pelikerrasta, joka aidosti sai nolla pistettä, joten tarkista avaimen olemassaolo ennen kuin luet sen. |
performance joskus number | number | Tyypin oma mittari sille, kuinka hyvin meni, jos sellainen on käytössä — esimerkiksi sanaa minuutissa näppäilyharjoituksessa. |
attempts joskus number | number | Monesko yritys tämä on: 1 ensimmäisellä kerralla, yksi lisää joka uudella aloituksella. Vain tyypeillä, jotka päättävät pelikerran kesken ja laskevat uusintayritykset. |
knockedOut joskus boolean | boolean | Pelikerta päättyi väärään vastaukseen ja on ohi tulematta valmiiksi. |
hasAlternateCompletion joskus boolean | boolean | Aktiviteetti saatiin valmiiksi tavalla, joka ei yllä 100 %:iin — kokonaan vastattu Quiz, ratkaistu ratkaisukenttä. Kohtele sitä valmistumisena. |
missedKeys joskus array | array | Merkit, joissa pelaaja jatkuvasti erehtyi, eniten erehdytty ensin. Vain näppäilyharjoituksessa. |
contentVersion joskus number | number | Mitä versiota aktiviteetin sisällöstä vastaan tätä pelattiin. Se muuttuu, kun omistaja muokkaa kysymyksiä, joten vanha tulos erottuu tuoreesta. |
{
"activityKey": "-Nq8sample_activity_key",
"playerUid": "kK3r9TzSampleAnonymousUid",
"player": {
"name": "Ava Ortega",
"email": "ava@school.example",
"class": "5B"
},
"progress": 100,
"timePassed": 243120,
"lastPlayedAt": 1758297843120,
"createdAt": 1758297600000,
"playerInput": {
"-Nq8item_one": "Lisbon",
"-Nq8item_two": "1969"
},
"correctUids": {
"-Nq8item_one": true,
"-Nq8item_two": false
},
"score": 800,
"contentVersion": 1757923200000
}Kenttä, joka ei sovellu, jätetään pois JSON:sta sen sijaan, että se lähetettäisiin null-arvona tai nollana. Näin tyyppi, joka ei pisteytä pelikertaa, erotetaan pelikerrasta, joka pisteytyi nollaan — lue siis oletusarvolla äläkä koskaan oleta, että avain on olemassa.
Aktiviteetin nollaaminen sivultasi
Yksi komento kulkee toiseen suuntaan. Kun "Hyväksy komennot upottavalta sivulta" on kytketty päälle, upottava sivu voi tyhjentää pelaajan vastaukset ja palauttaa aktiviteetin alkuun — omaa "yritä uudelleen" -painiketta varten kehyksen ulkopuolella.
const frame = document.querySelector('iframe').contentWindow;
// Sent to the frame, from the page that embeds it — no other sender is
// accepted, and the activity has to have the trigger setting switched on.
frame.postMessage({ trigger: { type: 'reset' } }, 'https://puzzel.org');Tuloksen lähettämiselle, lopetusviestin avaamiselle tai kysymykseen hyppäämiselle ei ole viestiä. Viesti, joka pyytää muuta kuin nollausta, jätetään huomiotta.
Komento hyväksytään vain sivulta, joka kehystää aktiviteetin, eikä mistään muualta — ei sisarkehykseltä, ei sivulla olevalta skriptiltä. Asetus on oletuksena pois päältä, joten kytke se päälle niille aktiviteeteille, joita ohjaat.
Oman pelaajaidentiteetin tuominen mukaan
Jos alustasi jo tietää, kuka pelaa, aktiviteetin ei tarvitse kysyä sitä uudelleen. Kaksi kättelyä on olemassa, molemmat sivullesi upotettua aktiviteettia varten, ja molemmat me kytkemme päälle emmekä sinä editorista — ne muuttavat sen, kenelle tulos kuuluu, joten ne otetaan käyttöön yhdessä kanssasi, ei valintaruudusta.
Aktiviteetti ilmoittautuu viestillä 'app-loaded' ja odottaa. Sivusi lähettää pelaajan tiedot takaisin, ja tulos tallennetaan hänen nimiinsä ilman, että pelaaja kirjoittaa mitään tai näkee rekisteröitymisnäyttöä.
Sama kättely, mutta sivusi lähettää identiteetintarjoajasi myöntämän JWT:n itse kenttien sijaan. Vahvistamme sen tilillesi määritettyjä myöntäjiä vasten, ennen kuin pelaaja päästetään sisään, joten identiteetti todistetaan eikä vain väitetä — tämä on se, jota kannattaa pyytää, kun tuloksen täytyy olla luotettava.
window.addEventListener('message', (event) => {
if (event.origin !== 'https://puzzel.org') return;
// The activity says it is ready for a player.
if (event.data === 'app-loaded') {
frame.postMessage(
{
player: { name: 'Ava Ortega', email: 'ava@school.example', class: '5B' },
// true starts a fresh attempt instead of resuming this player's last one
should_reset: false
},
'https://puzzel.org'
);
}
// Signed in; the board is coming.
if (event.data?.success === true) hideYourOwnSpinner();
});Kerro, kumman näistä kahdesta haluat ja mihin aktiviteetit upotetaan, niin otamme tilisi käyttöön ja käymme sen läpi kanssasi.
Lähetä meille sähköpostia identiteetistäAktiviteettien luominen omasta järjestelmästäsi
Kaikki edellä on tuloksesta, joka tulee ulos. Toiseen suuntaan — aktiviteettien tekeminen sisällöstä, joka sinulla jo on — on Puzzle API: yksi POST per aktiviteettityyppi, ja saat takaisin avaimen ja upotettavan URL-osoitteen.
Lue API-viitedokumentaatioKun valmis liitäntä on parempi vastaus
Jos toisella puolella on oikea LMS, et todennäköisesti tarvitse mitään tästä. Arvosanat voivat palautua sen arvosanataulukkoon itsestään, eikä sinun tarvitse isännöidä mitään.
Käynnistetään LMS:n sisältä, ja pistemäärä kirjoitetaan takaisin sen arvosanataulukkoon.
Julkaise aktiviteetti tehtävänä ja anna arvosanojen palautua automaattisesti.
Kurssialustat, jäsensivustot, intranetit ja mikä tahansa itse rakentamasi järjestelmä ovat juuri sitä varten, mitä tämän sivun kanavat tarjoavat. Upotus ja valmistumissignaali kattavat suurimman osan siitä.
Mitä ei ole
Ettet turhaan etsi näitä:
- Ei päätepistettä tulosten lukemiseen takaisin. API luo aktiviteetteja; tulokset lähtevät tämän sivun kanavien kautta tai hallintapaneelisi vientien kautta.
- Ei allekirjoitusta webhookissa. Ei ole mitään, mitä vasten pyyntö voisi tarkistaa, minkä vuoksi tuloksen ei pitäisi olla ainoa asia, joka kannattelee jotain tärkeää.
- Ei tilinlaajuista webhookia. URL-osoite on aktiviteettikohtainen asetus, joten kopioimasi aktiviteetti kuljettaa sen mukanaan, ja uusi aktiviteetti aloittaa ilman sitä.
- Ei mitään joukkuepelissä tai livehuoneessa. Molemmat viestikanavat ja webhook on tarkoitettu yksinpeliin, ja asetukset kytkeytyvät itse pois päältä, kun moninpeli on käytössä.
- Ei toimitusjonoa. Mitään ei tallenneta ja lähetetä uudelleen — seuraava tallennus on uusintayritys, ja pelikerran viimeinen kutsu on se, joka ratkaisee.
Jokin ei toimi odotetusti?
Lähetä pyyntö, jota kokeilit, ja virhe, jonka sait vastaukseksi, niin saat oikean vastauksen henkilöltä, joka kirjoitti päätepisteen.
Lähetä sähköpostia tukeen