Lingara Lingara Documentazione Guide API Librerie App Crea App web
Lingua: Italiano

Contesto e consenso

Questa pagina è tradotta dall'inglese. Se le due versioni differiscono, fa fede la pagina in inglese. Leggi la pagina in inglese

La tua app viene a sapere qualcosa di uno studente solo tramite porzioni di contesto. Ogni porzione è un piccolo record con campi fissi. Il tuo manifest elenca le porzioni che chiede, lo studente acconsente a ciascuna quando installa la tua app, e Lingara invia una porzione solo finché entrambe le condizioni restano valide.

Le porzioni

PorzioneCampoCosa contiene
languagessource_langLa lingua da cui lo studente studia, come tag di lingua, ad esempio en.
target_langLa lingua che sta imparando.
levelIl suo livello in quella lingua, da 1 a 9, se ne ha impostato uno.
plan_summaryplan_idL’id del suo ultimo piano di lezione, che distingue un piano dall’altro. La tua app non può usarlo per recuperare il piano, perché il token della tua app legge il tuo account, non quello dello studente.
titleIl titolo generato del piano, di al massimo 120 caratteri, se ne ha uno.
target_langLa lingua che il piano insegna.
set_countQuanti set ha il piano, al massimo 200.
sets_completedQuanti di quei set lo studente ha completato.
review_duedueQuante carte sono da ripassare adesso, al massimo 100000.
learnedQuante parole ha imparato, al massimo 100000.
tutor_topictopicL’argomento della sua ultima chat con il tutor, da 1 a 120 caratteri. Proviene dal titolo di un piano o dalla schermata in cui si trova, mai dalle sue parole.

Cosa nessuna porzione contiene

Nessuna porzione contiene un indirizzo email, un nome, un id utente o qualsiasi cosa lo studente abbia digitato. La tua app sa chi è lo studente dal subject della richiesta, un valore stabile che è diverso per ogni app. Il token della tua app legge il tuo account, mai quello dello studente, quindi le porzioni sono tutto ciò che la tua app sa di lui.

Consenso

  • Lo studente acconsente a ogni porzione quando installa la tua app. Per cambiare ciò a cui ha acconsentito, disinstalla la tua app e la installa di nuovo.
  • Se modifichi il tuo manifest per chiedere meno porzioni, quelle che hai tolto si fermano subito.
  • Se lo modifichi per chiederne di più, le nuove porzioni non raggiungono nessuno studente finché non reinstalla l’app.
  • Lingara verifica di nuovo il consenso a ogni richiesta e scarta qualsiasi porzione a cui lo studente non ha acconsentito o che il tuo manifest non chiede più. Anche una porzione che non rispetta il suo record viene scartata, mai l’intera richiesta.

L’esempio qui sotto costruisce la sua riga a partire dalle porzioni che ha ricevuto e non chiama alcuna API.

Linguaggio dell'esempio di codice

TypeScript

// The app's own client reads its owner's account, never the learner's. The
// slices are all a render knows about the learner.
function planLine(request: AppRenderRequest): string {
  let line = "";
  for (const slice of request.context) {
    // A slice is present only when the learner agreed to share it.
    if (slice.kind === "languages") line += `${slice.source_lang} → ${slice.target_lang}. `;
    if (slice.kind === "plan_summary") line += `${slice.sets_completed}/${slice.set_count} sets.`;
  }
  return line;
}

Rust

// The app's own client reads its owner's account, never the learner's. The
// slices are all a render knows about the learner.
/// The learner's target language and, when they shared their plan, its
/// `(sets_completed, set_count)`.
fn shared_plan(request: &AppRenderRequest) -> (String, Option<(u32, u32)>) {
    let (mut target_lang, mut progress) = (String::from("zh"), None);
    for slice in &request.context {
        match slice {
            ContextSlice::Languages(languages) => target_lang = languages.target_lang.clone(),
            ContextSlice::PlanSummary(summary) => progress = Some((summary.sets_completed, summary.set_count)),
            _ => {}
        }
    }
    (target_lang, progress)
}

Go

// The app's own client reads its owner's account, never the learner's.
// The slices are all a render knows about the learner.
//
// Each slice is present only when the learner agreed to share it.
card := lingaraapps.NewCard().Heading("Your plan", 1)
for _, slice := range req.Context {
	switch s := slice.(type) {
	case lingaraapps.ContextSliceLanguages:
		card.Text(fmt.Sprintf("Learning %s from %s", s.TargetLang, s.SourceLang))
	case lingaraapps.ContextSlicePlanSummary:
		card.Text(fmt.Sprintf("%d of %d sets done", s.SetsCompleted, s.SetCount))
	}
}

Java

import com.getlingara.apps.Card;
import com.getlingara.apps.Reply;
import com.getlingara.apps.model.AppRenderRequest;
import com.getlingara.apps.model.ContextSlice;
import com.getlingara.apps.model.ContextSliceLanguages;
import com.getlingara.apps.model.ContextSlicePlanSummary;

// The app's own client reads its owner's account, never the learner's. The slices are all a
// render knows about the learner.
static Reply render(AppRenderRequest request) {
  Card.Builder card = Card.card();
  // A slice is present only when the learner agreed to share it; the context is read-only.
  for (ContextSlice slice : request.getContext()) {
    if (slice instanceof ContextSliceLanguages languages) {
      card.heading("Learning " + languages.targetLang(), 1);
    } else if (slice instanceof ContextSlicePlanSummary summary) {
      card.text(summary.setsCompleted() + " of " + summary.setCount() + " sets done");
    }
  }
  return card.heading("Today", 2).build();
}

Kotlin

import com.getlingara.apps.kotlin.Reply
import com.getlingara.apps.kotlin.card
import com.getlingara.apps.kotlin.model.AppRenderRequest
import com.getlingara.apps.kotlin.model.ContextSliceLanguages
import com.getlingara.apps.kotlin.model.ContextSlicePlanSummary

// The app's own client reads its owner's account, never the learner's. The slices are all a
// render knows about the learner.
fun renderWithContext(request: AppRenderRequest): Reply {
    // A slice is present only when the learner agreed to share it; the context is read-only.
    val languages = request.context.filterIsInstance<ContextSliceLanguages>().firstOrNull()
    val summary = request.context.filterIsInstance<ContextSlicePlanSummary>().firstOrNull()
    return card {
        heading("Learning ${languages?.targetLang ?: "today"}", 1)
        if (summary != null) {
            text("${summary.setsCompleted} of ${summary.setCount} sets done")
        }
    }
}

Ruby

# The app's own client reads its owner's account, never the learner's. The
# slices are all a render knows about the learner.
#
# A slice is present only when the learner agreed to share it.
request.context.filter_map do |slice|
  case slice
  in Lingara::Apps::ContextSliceLanguages(source_lang:, target_lang:)
    "#{source_lang} → #{target_lang}."
  in Lingara::Apps::ContextSlicePlanSummary(sets_completed:, set_count:)
    "#{sets_completed}/#{set_count} sets."
  else nil
  end
end.join(" ")

PHP

use Lingara\Apps\Generated\ContextSliceLanguages;
use Lingara\Apps\Generated\ContextSlicePlanSummary;

function planLine(AppRenderRequest $request): string
{
    // The app's own client reads its owner's account, never the learner's. The
    // slices are all a render knows about the learner.
    $line = '';
    // A slice is present only when the learner agreed to share it.
    foreach ($request->getContext() as $slice) {
        if ($slice instanceof ContextSliceLanguages) {
            $line .= "{$slice->sourceLang} → {$slice->targetLang}. ";
        } elseif ($slice instanceof ContextSlicePlanSummary) {
            $line .= "{$slice->setsCompleted}/{$slice->setCount} sets.";
        }
    }
    return $line;
}

Vedi anche