Przypsianie kilku zmiennym wartości z tablicy

Przypsianie kilku zmiennym wartości z tablicy
P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
2

Mój błąd. Niepotrzebny jest wpis w sessionStorage o kluczu selected, ponieważ kod powinien inaczej działać, niż myślałem. Powinien działać tak, że za każdym odświeżeniem strony powinno wyświetlać się to samo pytanie. Nic więcej, nic mniej. W związku z tym potrzebny jest jedynie jeden wpis w sessionStorage, czyli lastQuestionIndex. Żeby to osiągnąć, dwie rzeczy:

(1) Handler zdarzenia click przycisku "Wyślij" powinien tak wyglądać:

Kopiuj
btnSubmit.addEventListener('click', function() {
  if (validateIfChecked() === true) {
    sessionStorage.removeItem('lastQuestionIndex');
    for (let i = 0; i < input.length; i++) {
      input[i].checked = false;
    }
    showRandomQuestion();
  } else {
    alert('Zaznacz coś');
  }
});

(2) Cały kod z if-em na początku funkcji showRandomQuestion powinien tak wyglądać (czyli usuwasz ten if, co jest, i wstawiasz ten kod):

Kopiuj
if (sessionStorage.getItem('lastQuestionIndex') === null) {
  displayQuestQizIndex = getRandomQuestion();
  sessionStorage.setItem('lastQuestionIndex', displayQuestQizIndex);
} else {
  displayQuestQizIndex = sessionStorage.getItem('lastQuestionIndex');
}

U mnie wydaje się działać. Jeśli czegoś nie rozumiesz, pytaj. Zachęcam Cię, byś próbował zrozumieć działanie całego kodu, który ja Ci daję. Jak widać, też mogę popełniać błędy, więc będziesz mieć przynajmniej szansę je wyłapać sam.


PS Atrybut autocomplete w kodzie HTML wydaje się nie działać w zamierzony sposób – najlepiej go usunąć.

P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

A gdybym chciał zrobić podobny myk z pytaniami żeby po odświeżeniu strony nie zmieniała się kolejność pytań to rozumiem że muszę zastosować podobny kod?

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
1

Kod powinien być podobny, tak. Trzeba by najprawdopodobniej:

  1. zapisywać tablicę z indeksami opowiedzi w sessionStorage wtedy, gdy wpis lastQuestionIndex w sessionStorage ma wartość null;
  2. odczytywać ją (tzn. przypisywać ją zmiennej variants) wtedy, gdy wpis lastQuestionIndex w sessionStorage nie ma wartości null.
P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Napisałem ten kod ale dostaje coś takiego https://jsfiddle.net/14nxbL7s/

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
0

Ciężko pomóc tutaj bez dawania kodu, ale spróbuję. W funkcji showRandomQuestion:

(1) Wynik funkcji getRandomVariants powinnien być przypisywany do zmiennej variants wyłącznie wtedy, kiedy wpis lastQuestIndex ma wartość null. Natomiast u Ciebie dzieje się to zawsze, niezależnie jaką wartość ma ten wpis (linia let variants = getRandomVariants(displayQuestQizIndex);).

(2) Na wartość answersIndices powinieneś ustawiać nowy, oddzielny wpis lastAnswersIndices (taka nazwa jest najlepsza moim zdaniem). Natomiast Ty ustawiasz na nią wpis lastQuestIndex, przez co nadpisujesz go, a nie powinieneś (linia sessionStorage.setItem('lastQuestIndex', answersIndices);). Podobnie z pobieraniem: powinieneś pobierać wartość tego nowego wpisu, a nie wpisu lastQuestIndex (linia variants = sessionStorage.getItem('lastQuestIndex');).

(3) To nie błąd, ale rzecz utrudniająca kod: niepotrzebnie dodałeś drugą instrukcję if. Już jest jedna wyżej, można ją wykorzystać (zwróć uwagę, że warunki w obu tych instrukcjach są takie same).

P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Teraz pojawia się pętla nieskończona https://jsfiddle.net/zb231to0/

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
0

Nie widzę pętli nieskończonej. O czym dokładnie mówisz?

Natomiast kod tak czy siak jest nie do końca dobry. W drugiej instrukcji if w warunku jest sprawdzenie, czy wpis lastAnswersIndices ma wartość null, a powinno być sprawdzenie, czy wpis lastQuestIndex ma wartość null. (To różnica, ponieważ, zauważ, wpis lastQuestIndex jest usuwany w handlerze kliknięcia na przycisk Submit, a wpis lastAnswersIndices nie jest).

P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Ok nie ma już tej pętli nieskończonej. Teraz jest to https://jsfiddle.net/8vdeajtr/2/

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
1
  1. Wcześniej pisałem, że obie instrukcje if mogłyby być razem, ale teraz zmienię zdanie i napiszę, że muszą być razem (czyli musi być tylko jedna instrukcja if, w której będzie kod obu instrukcji). Inaczej w pierwszej instrukcji, tak jak teraz jest, będzie zmieniać się kod, który jest sprawdzany w warunku drugiej instrukcji, a to niepoprawnie (błąd w logice kodu).
  2. Całkiem zapomniałem, że wartości kluczy sessionStore są konwertowane do typu string przed zapisaniem. A w przypadku odczytu wartości zmiennej lastAnswersIndices potrzebna nam jest tablica, a nie ciąg znaków. W związku z tym trzeba zrobić dwie rzeczy:
    2.1. teraz wartość zmiennej lastAnswersIndices jest zapisywana bezpośrednio do sessionStorage; natomiast powinna być konwertowana przed tym zapisem do ciągu znaków za pomocą metody JSON.stringify;
    2.2. teraz wartość wpisu lastAnswersIndices jest przypisywana bezpośrednio do zmiennej variants; natomiast powinna być przed tym przypisaniem parsowana za pomocą metody JSON.parse.
P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
0
  1. Nadal są dwie instrukcje if.
  2. Metoda JSON.stringify jest użyta w dobrym miejscu, ale metoda JSON.parse już nie. Ta ostatnia powinna być umieszczona po pobraniu wartości z sessionStorage, a teraz jest umieszczona przed tym.
  3. To nie błąd, ale dobrze byłoby inicjalizować zmienną variants pustą tablicą w momencie deklaracji.
P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Napisałeś wcześniej że '''obie instrukcje if mogłyby być razem, ale teraz zmienię zdanie i napiszę, że muszą być razem (czyli musi być tylko jedna instrukcja if, w której będzie kod obu instrukcji)''' no to jest jedna:

Kopiuj
	let variants = [];
	if (sessionStorage.getItem('lastQuestIndex') === null) {
		variants = getRandomVariants(displayQuestQizIndex);
		variants = sessionStorage.getItem(JSON.parse('lastAnswersIndices'));
		sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
	}
P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Chodzi o coś takiego?

Kopiuj
	if (condition) {
		if (sessionStorage.getItem('lastQuestIndex') === null) {
			variants = getRandomVariants(displayQuestQizIndex);
			variants = sessionStorage.getItem(JSON.parse('lastAnswersIndices'));
			sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
		}		
	}
Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
1

W sumie nie zauważyłem wcześniej, że usunąłeś blok else. Nie, nie chodzi o usunięcie bloku else. Pisząc, że powinna być jednak instrukcja if, miałem na myśli, że w jednej instrukcji powinny być ustawiane zarówno zmienna displayQuestQizIndex, jak i zmienna variants; natomiast w kodzie pod linkiem do JSFiddle, który zamieściłeś ostatnio, są dwie instrukcje if. I w tej jednej instrukcji if nadal powinien być blok else (w którym będą pobierane wartości kluczów wpisów lastQuestIndex oraz lastAnswersIndices).

P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

O to chodzi?

Kopiuj
	let variants = [];
	if (sessionStorage.getItem('lastQuestIndex') === null) {
		sessionStorage.setItem('lastQuestIndex', variants);
		sessionStorage.setItem('lastQuestIndex', displayQuestQizIndex);
	} else {
		variants = sessionStorage.getItem(JSON.parse('lastQuestIndex'));
		sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
	}
Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
1

Może wyjaśnię bliżej, o co mi chodziło, gdy napisałem, że "powinny być ustawiane zmienne".

  1. Przez "ustawienie zmiennej" rozumiem każdą z następujących instrukcji:
Kopiuj
zmienna = coś; // Ustawienie zmiennej
var zmienna = coś; // Również ustawienie zmiennej
let zmienna = coś; // Również ustawienie zmiennej
  1. Przez "ustawienie stałej" rozumiem następującą instrukcję:
Kopiuj
const zmienna = coś; // Ustawienie stałej

Mała uwaga: może byłem wcześniej nieprecyzyjny. Zgodnie z dokumentacją MDN -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const instrukcja zawierająca słowo kluczowe const jest "stałą", a nie "zmienną" (jak mogłem wcześniej nieprecyzyjnie pisać).

Ponadto:

  1. My korzystamy z właściwości sessionStorage obiektu Window (piszesz samo sessionStorage, ale mógłbyś Window.sessionStorage). Ona daje nam dostęp do tzw. obiektu Storage. Zgodnie z dokumentacją MDN -> https://developer.mozilla.org/en-US/docs/Web/API/Storage interfejs Storage przechowuje pary klucz-wartość. (Nie pytaj mnie, czemu raz Storage nazywany jest "obiektem", a kiedy indziej "interfejsem"; nie wiem; @szatkus , @LukeJL , @Freja Draco , wiecie?).

Ja nazywam poszczególne elementy obiektu Storage "wpisami"; trochę odmiennie od dokumentacji MDN, przyznam. Robię tak na podobieństwo terminologii używanej w przypadku typu Object, gdzie jest np. metoda entries() obiektu Object (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries). "Entry" tłumaczę jako "wpis". W interfejsach webowych te moje "wpisy" nazywane są "items"; dlatego też wywoływane w naszym kodzie metody getItem i setItem właśnie tak się nazywają. "Item" może być tłumaczone jako "element".

Ale teraz myślę, że terminologia, której używam, jest cokolwiek niepoprawna: jak teraz zauważyłem, "entry" może być tłumaczone jako "hasło". Poniżej będę już pisać "hasło" zamiast "wpis".

W związku z tym wszystkim, co powyżej:

  1. W bloku if instrukcji if powinny być zawarte następujące instrukcje:
    4.1. przypisanie zmiennej displayQuestQizIndex losowego indeksu pytania, używając funkcji getRandomQuestion;
    4.2. przypisanie zmiennej variants tablicy z indeksami odpowiedzi pytania o wylosowanym indeksie, używając funkcji getRandomVariants;
    4.3. ustawienie wartości hasła lastQuestIndex obiektu sessionStorage na wylosowany indeks;
    4.4. ustawienie wartości hasła lastAnswersIndices obiektu sessionStorage na tablicę z indeksami odpowiedzi pytania o wylosowanym indeksie, używając metody stringify obiektu JSON.

  2. W bloku else instrukcji if powinny być zawarte następujące instrukcje:
    5.1. przypisanie zmiennej displayQuestQizIndex wartości hasła lastQuestIndex obiektu sessionStorage;
    5.2. przypisanie zmiennej variants wartości hasła lastAnswersIndices obiektu sessionStorage, używając metody parse obiektu JSON.

(No, mam nadzieję, że nigdzie nie zrobiłem błędu).


PS Jak gdzieś widzisz w moich postach jakąś nieścisłość, czy wyraźny błąd, od razu mi pisz, zachęcam. Chciałbym najlepiej Ci pomagać, ale czasem popełnię jakąś literówkę czy błąd logiczny.

  • Rejestracja: dni
  • Ostatnio: dni
0

Ten kod nie przeszedłby review w żadnej poważnej firmie.

P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Coś nie działa https://jsfiddle.net/4edrnj2t/. Możesz sprawdzić czy wszystko napisałem zgodnie z twoimi wytycznymi?

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
0
  1. Nadal są dwie instrukcje if. Powinna być jedna.
  2. Metoda JSON.parse nadal parsuje nie to, co powinna.
P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Teraz to wygląda tak

Kopiuj
	let displayQuestQizIndex = -1;
	let variants = [];
	if (sessionStorage.getItem('lastQuestIndex') === null) {
		displayQuestQizIndex = getRandomQuestion();
		variants = getRandomVariants(displayQuestQizIndex);
		sessionStorage.setItem('lastQuestIndex', displayQuestQizIndex);
		sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
	} else {
		displayQuestQizIndex = sessionStorage.getItem('lastQuestIndex');
		variants = sessionStorage.getItem(JSON.parse('lastAnswersIndices'));
	}

wstawiam tak tylko dla uwagi

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
0

To jest druga instrukcja if (zgodnie z ostatnim kodem), i właśnie tę powinieneś zostawić.

P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Czyli to co mam tutaj

Kopiuj
    let displayQuestQizIndex = -1;
    let variants = [];
    if (sessionStorage.getItem('lastQuestIndex') === null) {
        displayQuestQizIndex = getRandomQuestion();
        variants = getRandomVariants(displayQuestQizIndex);
        sessionStorage.setItem('lastQuestIndex', displayQuestQizIndex);
        sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
    } else {
        displayQuestQizIndex = sessionStorage.getItem('lastQuestIndex');
        variants = sessionStorage.getItem(JSON.parse('lastAnswersIndices'));
    }

powinienem zostawić?

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
1

Tak, właśnie tak.

P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Ok

P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Teraz mam proble z tym JSON.parse. Testuje różne opcje i nie działa mam taki błąd JSON.parse: unexpected character at line 1 column 1 of the JSON data

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
1

Pokaż kod.

Powinno być tak: najpierw pobierasz wartość hasła lastAnswersIndices z sessionStorage, a następnie tę pobraną wartość parsujesz za pomocą metody JSON.parse.


PS Żeby zrozumieć, po co w ogóle jest to parsowanie, to możesz roboczo wyświetlić sobie tę pobraną wartość, np. za pomocą metody console.log. My potrzebujemy tablicy, a pobrana wartość jest ciągiem znaków.

P1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 640
0

Gdybym chciał zrobić dodatkowo jeszcze licznik który by zliczał ilość punktów to musiałbym na początku zdefiniować zmienną z wartością 0 która by przechowywała ilość punktów, sprawdzanie poprawności odpowiedzi(czyli na ile pytań użytkownik udzielił poprawnej odpowiedzi, a na ile złej), ustalenie po jakiej ilości pytań zakończyć gre(chodzi o to żeby użytkownik odpowiedział na cztery pytania ale żeby każde pytanie było unikatowe a nie występowało po sobie). Wydaje mi się że musze zaimplementować tą funkcjonalność gdyż pytania wyświetlają mi się w losowej kolejności a nie odgórnie ustalonej. Czy jeszcze coś można dodać do takiego licznika?

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
1

Gdybym chciał zrobić dodatkowo jeszcze licznik który by zliczał ilość punktów to musiałbym na początku zdefiniować zmienną z wartością 0 która by przechowywała ilość punktów (…)

Tak, między innymi taka zmienna będzie potrzebna.

(…) sprawdzanie poprawności odpowiedzi(czyli na ile pytań użytkownik udzielił poprawnej odpowiedzi, a na ile złej) (…)

To raczej nie jest już część licznika.

(…) ustalenie po jakiej ilości pytań zakończyć gre(chodzi o to żeby użytkownik odpowiedział na cztery pytania ale żeby każde pytanie było unikatowe a nie występowało po sobie).

Tego nie rozumiem. Także raczej nie jest to część wspomnianego licznika. Czy chodzi Ci o to, że użytkownik ma określać liczbę pytań, zanim rozpocznie grę?

Przed jakąkolwiek zmianą proponowałbym trochę ulepszyć istniejący kod. :) (Jeśli mam coś zaproponować, to prosiłbym o pokazanie kodu po ostatnich zmianach).


PS

Wydaje mi się że musze zaimplementować tą funkcjonalność gdyż pytania wyświetlają mi się w losowej kolejności a nie odgórnie ustalonej.

Tego też nie rozumiem.

Czy jeszcze coś można dodać do takiego licznika?

Ja bym to ogólnie widział tak, że licznik odpowiedzi powinien liczyć odpowiedzi, i nic więcej nie robić. Jeśli chodzi o inne dodatkowe funkcjonalności, to można by dodawać je ogólnie do programu (jako odrębne od licznika). Przy okazji możesz zerknąć na ten artykuł -> https://pl.wikipedia.org/wiki/Zasada_jednej_odpowiedzialno%C5%9Bci (I przy okazji miałbym pytanie: czy wolisz, żebym dawał artykuły po polsku, czy po angielsku?)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.