Lingara Lingara Documentación Guías API Bibliotecas Apps Crear Aplicación web
Idioma: Español

Contexto y consentimiento

Esta página está traducida del inglés. Si ambas difieren, la página en inglés es la correcta. Leer la página en inglés

Tu app solo sabe algo de un estudiante a través de fragmentos de contexto. Cada fragmento es un registro pequeño con campos fijos. Tu manifiesto enumera los fragmentos que pide, el estudiante acepta cada uno al instalar tu app, y Lingara envía un fragmento solo mientras ambas cosas sigan vigentes.

Los fragmentos

FragmentoCampoQué contiene
languagessource_langEl idioma desde el que estudia el estudiante, como etiqueta de idioma, por ejemplo en.
target_langEl idioma que está aprendiendo.
levelSu nivel en él, de 1 a 9, cuando ha establecido uno.
plan_summaryplan_idEl id de su plan de lección más reciente, que distingue un plan de otro. Tu app no puede obtener el plan con él, porque el token de tu app lee tu propia cuenta, no la del estudiante.
titleEl título generado del plan, de como máximo 120 caracteres, cuando lo tiene.
target_langEl idioma que enseña el plan.
set_countCuántos bloques tiene el plan, como máximo 200.
sets_completedCuántos de esos bloques ha terminado el estudiante.
review_duedueCuántas tarjetas están pendientes ahora, como máximo 100000.
learnedCuántas palabras ha aprendido, como máximo 100000.
tutor_topictopicDe qué trata su chat más reciente con el tutor, de 1 a 120 caracteres. Procede del título de un plan o de la pantalla en la que está, nunca de sus propias palabras.

Lo que ningún fragmento lleva

Ningún fragmento lleva una dirección de correo, un nombre, un id de usuario ni nada que el estudiante haya escrito. Tu app sabe quién es el estudiante por el subject de la solicitud, un valor estable que es distinto para cada app. El token de tu app lee tu propia cuenta, nunca la del estudiante, así que los fragmentos son todo lo que tu app sabe de él.

Consentimiento

  • El estudiante acepta cada fragmento al instalar tu app. Para cambiar lo que aceptó, desinstala tu app y la vuelve a instalar.
  • Si editas tu manifiesto para pedir menos fragmentos, los que quitaste se detienen de inmediato.
  • Si lo editas para pedir más, los fragmentos nuevos no llegan a ningún estudiante hasta que la reinstale.
  • Lingara vuelve a comprobar el consentimiento en cada solicitud y descarta cualquier fragmento que el estudiante no aceptó o que tu manifiesto ya no pide. Un fragmento que no encaja en su registro también se descarta, nunca la solicitud entera.

El ejemplo de abajo construye su línea a partir de los fragmentos que recibió y no llama a ninguna API.

Lenguaje del ejemplo de código

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;
}

Véase también