# timOhjeet
if (typeof textMessages === 'undefined') textMessages = {};
if (typeof lang === 'undefined') lang = "fi";

function getLang(data) {
   lang = data.answer_call_data?.markup?.lang || "fi";
}

function T(s) {
   const ts = textMessages[s]?.[lang];
   if (ts) return ts;
   return s;
}


cardTexts = {
  "Oikein!": {en: "Correct!"},
  "Kortit katsottu, tee uusi jako!":  {en: "Cards reviewed, deal again!"},
  "Pisteitä": {en: "Points"},
  "Kortteja ei saa liikuttaa tässä tehtävässä!": {en: "Cards are not allowed to move in this task!"},
  "Väärä määrä kortteja!": {en: "Wrong number of cards!"},
  "Punainen väärässä paikassa!": {en: "Red in wrong position!"},
  "Ei järjestyksessä!": {en: "Not in order!"},
  "Liian vähän osoituksia!": {en: "Too few pointings!"},
  "Liian paljon osoituksia!": {en: "Too many pointings!"},
  "Liian vähän sijoituksia!": {en: "Too few assignments!"},
  "Liian paljon sijoituksia!": {en: "Too many assignments!"},
  "Ei saa olla tyhjiä!": {en: "Empty places not allowed!"},
  "Ei saa olla musta!": {en: "Black not allowed!"},
  "Punainen ei 1. tyhjän kohdalla.": {en: "Red not in the first empty place."},
  "Musta ei ole kohdalla": {en: "Black not in correct place!"},
};

Object.assign(textMessages, cardTexts);

class PlayingCard {
    constructor(cardString) {
        if (!cardString) cardString = "";
        const match = cardString.match(/^([shdc])(\d{2})$/);
        if (!match) {
            this.suit = " ";
            this.value = -100;
            this.color = -10;
            this.id = "   ";
        } else {
            this.id = cardString;
            this.suit = match[1];
            this.value = parseInt(match[2], 10);
            this.color = (this.suit === "d" || this.suit === "h") ? 1: 0;
        }    
    }
}


function compareCards(a, b, jsparams) {
    const useSuit = jsparams.compareSuits ?? false;
    const suits = jsparams.suits || "csdh";
    if (a.value < b.value) return -1;
    if (a.value > b.value) return 1;
    if (!useSuit  || !a.suit || !b.suit) return 0;
    const ai = suits.indexOf(a.suit);
    const bi = suits.indexOf(b.suit);
    if (ai < bi) return -1;
    if (ai > bi) return 1;
    return 0;
}


function checkNoSave(data) {
    if (data.answer_call_data?.markup?.nosave) {
      // data.save_object = null;
      data.allow_save = false;
      // data.web.console = "";
    }
    return data;
}


function checkCardPoints(data, p, max, text) {
    if (max == 0) {
        data.points = 0;
        data.web.console = T("Pisteitä") + " " + data.points + ".  "  + text;
        return checkNoSave(data);
    }   
    const answer = data.save_object?.c || {};
    const cntrs = answer.cntrs ?? [0,0];
    const move = p.move || [0, 1000000];
    const assign = p.assign || [0, 1000000];
    const mul = p.mul || 0.5;
    data.points = max*(p.maxp || 1);
    if (cntrs[0] < move[0])   { text += " " + T("Liian vähän osoituksia!"); data.points *= 0.5; }
    if (cntrs[0] > move[1])   { text += " " + T("Liian paljon osoituksia!"); data.points *= 0.5; }
    if (cntrs[1] < assign[0]) { text += " " + T("Liian vähän sijoituksia!"); data.points *= 0.5; }
    if (cntrs[1] > assign[1]) { text += " " + T("Liian paljon sijoituksia!"); data.points *= 0.5; }
    data.web.console = T("Pisteitä") + " " + data.points + ".  "  + text;
    return checkNoSave(data);
}


function getAnswerJSParams(data, p) {
    getLang(data);
    const answer = data.save_object?.c || null;
    const answerCallData = data.answer_call_data || {};
    const markup = answerCallData.markup || {};
    const jsparams = markup.jsparams || {};
    if (!answer) return [null, null, null, checkNoSave(data)];
    const allowOpen = (p?.open ?? false) || (jsparams.startOpen ?? false);
    if (!allowOpen && answer.moved) return [null, null, null, checkCardPoints(data, null, 0, T("Kortit katsottu, tee uusi jako!"))]; 
    // print("\<pre\>" + JSON.stringify(answer, null, 2) + "\</pre\>");  // debuggausta varten
    // print("\<pre\>" + JSON.stringify(jsparams, null, 2) + "\</pre\>");  // debuggausta varten
    // print("\<pre\>" + JSON.stringify(answerCallData, null, 2) + "\</pre\>");  // debuggausta varten
    // print("\<pre\>" + JSON.stringify(markup, null, 2) + "\</pre\>");  // debuggausta varten
    const cardids = answer.cards || [];
    const cards = [];
    for (let cardid of cardids) cards.push(new PlayingCard(cardid));
    const n = jsparams.n ?? 8;
    if (!p.allowDiffN)
        if (cards.length != n) return [null, null, null, checkCardPoints(data, null, 0, T("Väärä määrä kortteja!"))];
    return [answer, jsparams, cards, null];
}


function checkMaxCard(data, p) {
    const [answer, jsparams, cards, ret] = getAnswerJSParams(data, p); 
    if (ret) return ret;
    const dir = p.dir ?? 1;
    const maxPos = (answer.ptrs?.[0] || 0) - 1;
    if (maxPos == -1 && cards.length == 0)  return checkCardPoints(data, null, 1, T("Oikein!"));
    let mi = 0;
    for (let i=1; i<cards.length; i++) {
        if (compareCards(cards[mi], cards[i], jsparams) * dir < 0) mi = i;  
    }
    if (mi != maxPos) return checkCardPoints(data, null, 0, T("Punainen väärässä paikassa!")); 
    return checkCardPoints(data, p, 1, T("Oikein!"));
}


function checkSort(data, p) {
    const [answer, jsparams, cards, ret] = getAnswerJSParams(data, p); 
    if (ret) return ret;
    const dir = p.dir ?? 1;
    for (let i=0; i+1<cards.length; i++) {
        if (compareCards(cards[i], cards[i+1], jsparams) * dir > 0) return checkCardPoints(data, p, 0, T("Ei järjestyksessä!"));  
    }
    return checkCardPoints(data, p, 1, T("Oikein!"));
}


function checkRedsOnLeft(data, p) {
    const [answer, jsparams, cards, ret] = getAnswerJSParams(data, p); 
    if (ret) return ret;
    for (let i=0; i+1<cards.length; i++) {
        if (cards[i].color < cards[i+1].color) return checkCardPoints(data, p, 0, T("Ei järjestyksessä!"));  
        if (cards[i].color < 0) return checkCardPoints(data, p, 0, T("Ei saa olla tyhjiä!")); 
    }
    if (cards[cards.length-1].color < 0) return checkCardPoints(data, p, 0, T("Ei saa olla tyhjiä!"));  
    return checkCardPoints(data, p, 1, T("Oikein!"));
}


function checkOnlyReds(data, p) {
    const [answer, jsparams, cards, ret] = getAnswerJSParams(data, p); 
    if (ret) return ret;
    let lastRed = 0;
    for (let i=0; i+1<cards.length; i++) {
        if (cards[i].color < cards[i+1].color) return checkCardPoints(data, p, 0, T("Ei järjestyksessä!"));  
        if (cards[i].color == 0) return checkCardPoints(data, p, 0, T("Ei saa olla musta!")); 
        if (cards[i].color == 1) lastRed = i+1;
    }
    if (cards[cards.length-1].color == 0) return checkCardPoints(data, p, 0, T("Ei saa olla musta!"));  
    if (cards[cards.length-1].color == 1) lastRed = cards.length;
    const redPos = (answer.ptrs?.[0] || 0) - 1;
    if (redPos != lastRed) return checkCardPoints(data, p, 0, T("Punainen ei 1. tyhjän kohdalla!"));  
    return checkCardPoints(data, p, 1, T("Oikein!"));
}


function checkFound(data, p) {
    const [answer, jsparams, cards, ret] = getAnswerJSParams(data, p); 
    if (ret) return ret;
    const blackPos = (answer.ptrs?.[1] || 0) - 1;
    const cardToFind = answer.c1 || "X";
    let pos = cards.length;
    for (let i=0; i<cards.length; i++) {
        if (cardToFind === cards[i].id) { pos = i; break; }
    }
    if (blackPos != pos) return checkCardPoints(data, p, 0, T("Musta ei ole kohdalla!"));  
    return checkCardPoints(data, p, 1, T("Oikein!"));
}


function checkInOrder(data, p) {
    const [answer, jsparams, cards, ret] = getAnswerJSParams(data, p); 
    if (ret) return ret;
    const blackPos = (answer.ptrs?.[1] || 0) - 1;
    const dir = p.dir ?? 1;
    let wrongPos = cards.length;
    for (let i=0; i+1<cards.length; i++) {
        if (compareCards(cards[i], cards[i+1], jsparams)* dir > 0) { wrongPos = i+1; break; }
    }
    if (blackPos != wrongPos) return checkCardPoints(data, p, 0, T("Musta ei ole kohdalla!"));      
    return checkCardPoints(data, p, 1, T("Oikein!"));
}

These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.