Herencia y visibilidad

 <?php

        class A {

            public $aa = "aa";
            private $bb = "bb";
            protected $cc = "cc";

        }

        class B extends A {

            public $dd = "dd";
            private $ee = "ee";

            function test() {
                echo $this->aa;
                echo $this->bb; //Esta no la imprime
                echo $this->cc;
                echo $this->dd;
                echo $this->ee;
            }

        }

        $obj = new B();
        $obj->test();

        echo $obj->aa;
        echo $obj->bb;//Esta no la imprime
        echo $obj->cc;//Esta no la imprime
        echo $obj->dd;
        echo $obj->ee;//Esta no la imprime

Ejercicio alumnos

class Alumno {

            private $nombre;
            private $nota;
            private $apellidos;

            //Set y get para todas las propiedades. La nota enter 0 y 10
            //El resto no vacíos
            //Función aprobado que nos devuelva true si la nota es >=5
            //Función nombre completo que nos devuelva el nombre y el apellido
            //¿Sería posible hacerlo como propiedad y no como función?
            //Functión mágica toString que nos devuelva nombre completo y nota

            function __set($name, $value) {
                if (property_exists($this, $name)) {
                    if ($name == 'nota') {
                        if ($value >= 0 && $value <= 10) {
                            $this->nota = $value;
                        } else {
                            throw new Exception("La nota debe estar entre 0 y 10");
                        }
                    } else {
                        if (!empty($value)) {
                            $this->$name = $value;
                        }
                    }
                }
            }

            function aprobado() {
                return $this->nota >= 5;
            }

            function __get($name) {
                if (property_exists($this, $name)) {
                    return $this->$name;
                } else {
                    if ($name == "nombreCompleto") {
                        return $this->nombreCompleto();
                    }
                }
            }

            function nombreCompleto() {
                return $this->nombre . " " . $this->apellidos;
            }

            public function __toString() {
                return $this->nombreCompleto." - ".$this->nota;
            }

        }

        $ana = new Alumno();
        $ana->nombre="Ana";
        $ana->apellidos="Pi";
        $ana->nota=7;
        echo $ana->nombreCompleto."<br/>";
        echo $ana;
        ?>

Setters y getters, diferentes formas

Con funciones:

 class Coche{
            private $marca;
            private $modelo;
            private $velocidad;
            
            //Crear las funciones que nos permitan poner y obtener valores
            //En el caso de la velocidad el valor permitido está entre 50 y 300
            //En el caso de marca y modelo comprobar que no esté vacío
            
            function setMarca($marca){
                if (!empty($marca)){
                    $this->marca=$marca;
                }
            }
            function setModelo($modelo){
                if (!empty($modelo)){
                    $this->modelo=$modelo;
                }
            }
            function setVelocidad($velocidad){
                if ($velocidad>=50 && $velocidad<=300){
                    $this->velocidad=$velocidad;
                } else{
                    throw new Exception("La velocidad debe estar entre 50 y 300");
                }
            }
            
            function getMarca(){
                return $this->marca;
            }
            function getModelo(){
                return $this->modelo;
            }
            function getVelocidad(){
                return $this->velocidad;
            }
        }
        
        $seat=new Coche();
        $seat->setMarca("Seat");
        $seat->setModelo("Panda");
        $seat->setVelocidad(180);
        print_r($seat);

Con __get y __set

     <?php
        class Coche {

            private $marca;
            private $modelo;
            private $velocidad;

            //Crear las funciones que nos permitan poner y obtener valores
            //En el caso de la velocidad el valor permitido está entre 50 y 300
            //En el caso de marca y modelo comprobar que no esté vacío

            function __get($name) {
                if (property_exists('Coche', $name)) {
                    return $this->$name;
                }
            }

            function __set($name, $value) {
                if ($name == "velocidad") {
                    if ($value >= 50 && $value <= 300) {
                        $this->velocidad = $value;
                    } else {
                        throw new Exception("La velocidad debe estar entre 50 y 300");
                    }
                } else {
                    if (!empty($value) && property_exists('Coche', $name)) {
                        $this->$name = $value;
                    }
                }
            }

        }

        $seat = new Coche();
        $seat->marca = "Seat";
        $seat->modelo = "Panda";
        $seat->velocidad = 180;
        $seat->color="rojo";
        echo $seat->modelo;
        echo $seat->color;
        print_r($seat);

Trivial: fallos

# nombre, pregunta
antes muerta que sencilla, ¿Cómo seleccionamos elementos con la clase ‘test’?
antes muerta que sencilla, Sintaxis de while en JS
antes muerta que sencilla, ¿Qué evento ocurre cuando clicamos en un elemento HTML?
antes muerta que sencilla, ¿Usando qué nos aseguramos en jQuery que el código se ejecuta al cargar la página?
antes muerta que sencilla, ¿Qué significa HTML?
antes muerta que sencilla, ¿Cómo seleccionamos un elemento con id ‘demo’?
antes muerta que sencilla, ¿Cómo añadimos una clase a un elemento con jQuery?
antes muerta que sencilla, Propiedad para cambiar el tipo de fuente de un elemento
arnaubuixo, ¿Cómo ponemos los párrafos de color rojo en jQuery?
arnaubuixo, ¿Cómo se hace un comentario en CSS?
arnaubuixo, Indica que HTML usaríamos para poner un vídeo en HTML
arnaubuixo, Indica que valor de la propiedad position nos permite colocar un elemento respecto a la página
arnaubuixo, ¿Con qué código ponemos negrita a todos los párrafos?
carmen, ¿Cual es la etiqueta para un salto de línea?
carmen, ¿Qué selecciona en jQuery $(‘p#intro’)?
carmen, ¿Usando qué nos aseguramos en jQuery que el código se ejecuta al cargar la página?
carmen, Sintaxis de while en JS
carmen, Indica que valor de la propiedad position nos permite colocar un elemento respecto a la página
carmen, Código para seleccionar todos los ‘p’ dentro de un ‘div’
carmen, ¿Cuál es la manera correcta de obtener el valor de una variable GET?
carmen, Etiquetas para escribir php
carmen, ¿Cómo enlazamos un CSS externo?
carmen, ¿Cómo creamos arrays en PHP?
carmen, ¿Cómo cambiamos el contenido de un elemento ‘p’ con id ‘demo’?
Eladelite, Indica que valor de la propiedad position nos permite colocar un elemento respecto a la página
Eladelite, ¿Qué evento ocurre cuando clicamos en un elemento HTML?
Eladelite, ¿Cuantas columnas usa el grid de bootstrap?
Eladelite, ¿Cómo ocultamos elementos en jQuery?
Eladelite, Código para seleccionar todos los ‘p’ dentro de un ‘div’
Eladelite, Indica el código correcto para sumar uno a la variable $count
Eladelite, Propiedad para cambiar el tipo de fuente de un elemento
Eladelite, ¿Qué selecciona en jQuery $(‘p#intro’)?
Eladelite, Operador en PHP para comprobar igualdad de valor y tipo
Eladelite, ¿Se puede usar Ajax en jQuery?
Eladelite, ¿Cómo seleccionamos un cliente cuyo nombre empieza por ‘a’
Eladelite, Código para aplicar color rojo a todos los h1
Eladelite, ¿Cuál es la manera correcta de obtener el valor de una variable GET?
Eladelite, ¿Usa jQuery los selectores CSS para seleccionar elementos?
Eladelite, ¿Cómo añadimos una clase a un elemento con jQuery?
Eladelite, Sintaxis de if en JS
Eladelite, ¿Qué carácter usa jQuery como atajo para sus instrucciones?
fabian, ¿Cómo se hace un comentario en CSS?
fabian, Indica que valor de la propiedad position nos permite colocar un elemento respecto a la página
Jordi, En bootstrap hay una clase para crear un botón grande ¿Cuál?
Jordi, Propiedad para cambiar el tipo de fuente de un elemento
Jordi, ¿Usa jQuery los selectores CSS para seleccionar elementos?
Jordi, Indica que valor de la propiedad position nos permite colocar un elemento respecto a la página
Jordi, ¿Qué carácter usa jQuery como atajo para sus instrucciones?
Jordi, Código para seleccionar todos los ‘p’ dentro de un ‘div’
Jordi, El código $(‘div’) ¿Qué selecciona?
Jordi, Sentencia SQL para modificar datos
Jordi, Que afirmación es correcta
Jordi, ¿Usando qué nos aseguramos en jQuery que el código se ejecuta al cargar la página?
Jose Antonio, ¿Qué selecciona en jQuery $(‘p#intro’)?
Jose Antonio, ¿Cómo cambiamos el contenido de un elemento ‘p’ con id ‘demo’?
Jose Antonio, ¿Cómo creamos arrays en PHP?
Jose Antonio, En bootstrap hay una clase para crear un botón grande ¿Cuál?
Jose Antonio, Indica que HTML usaríamos para poner un vídeo en HTML
Jose Antonio, ¿Cómo seleccionamos un cliente cuyo nombre empieza por ‘a’
Mario, Indica que valor de la propiedad position nos permite colocar un elemento respecto a la página
Mario, Indica el código correcto para sumar uno a la variable $count
Mario, En bootstrap hay una clase para crear un botón grande ¿Cuál?
Mario, Sentencia SQL para borrar datos
Mario, ¿Cómo se hace un comentario en CSS?
Martes Martes, ¿Qué etiqueta semántica se utiliza para especificar la cabecera de un documento?
Martes Martes, Indica que valor de la propiedad position nos permite colocar un elemento respecto a la página
Martes Martes, Sentencia SQl para obtener datos
Martes Martes, ¿cual de estas etiquetas designa una encabezado?
Martes Martes, ¿Con qué etiqueta creamos un desplegable en HTML?
Martes Martes, ¿Con qué código ponemos negrita a todos los párrafos?
Martes Martes, ¿Cómo redondeamos 7.25 al entero más cercano en js?
Martes Martes, Propiedad para cambiar el tipo de fuente de un elemento
Martes Martes, ¿Cómo ponemos los párrafos de color rojo en jQuery?
Martes Martes, Etiquetas para escribir php
Martes Martes, Sentencia SQL para modificar datos
roger, ¿Cómo redondeamos 7.25 al entero más cercano en js?
roger, Indica cómo harías un checkbox en HTML
roger, Indica que HTML usaríamos para poner un vídeo en HTML
roger, ¿Qué significa HTML?
roger, ¿Usando qué nos aseguramos en jQuery que el código se ejecuta al cargar la página?
roger, Indica que valor de la propiedad position nos permite colocar un elemento respecto a la página
roger, Pincha en la etiqueta utilizada para destacar un texto
roger, ¿Usa jQuery los selectores CSS para seleccionar elementos?
roger, ¿Cómo creamos arrays en PHP?
roger, Código para seleccionar todos los ‘p’ dentro de un ‘div’
roger, ¿Cómo se hace un comentario en CSS?
Roser, Propiedad para cambiar el tipo de fuente de un elemento
Roser, ¿Cómo seleccionamos un cliente cuyo nombre empieza por ‘a’
Roser, ¿Qué etiqueta semántica se utiliza para especificar la cabecera de un documento?
Victor Pessolato, ¿Con qué etiqueta creamos un desplegable en HTML?
Victor Pessolato, ¿Con qué carácter se cierran las etiquetas?

Páginas web Scrapping

Por ejemplo, wikipedia:

https://es.wikipedia.org/w/index.php?title=Categor%C3%ADa:Actores_de_Espa%C3%B1a&from=A

https://es.wikipedia.org/wiki/Categor%C3%ADa:Actores_de_Estados_Unidos

O las páginas amarillas:

https://www.paginasamarillas.es

(Recordemos que tenemos el script aquí: http://trifulcas.com/web-scrapping-paginas-amarillas/)

Flickr:

PALLET RACK

Gimnasios:

http://www.gimcat.com/clubs.html?provincia=08&id=38

http://www.gametronik.com/site/index.php

Trivial 2.0: Completo

libreria.php

<?php

function conectar() {
    $server = "localhost";
    $user = "root";
    $password = "";
    $db = "trivial";
    try {
        $conn = new PDO("mysql:host=$server;dbname=$db", $user, $password, [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"]);
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $conn;
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }
}

function getPregunta($idUsuario) {
    try {
        $conn = conectar();
        //Buscamos una pregunta que no se haya hecho a este usuario al azar
        $sql = "SELECT * FROM preguntas where idpreguntas not in (select idpreguntas from resultados where idusuarios=$idUsuario) order by rand() limit 1";
        $resul = $conn->query($sql);
        $fila = $resul->fetch();
        return $fila;
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }
}

function getPuntuacion($idUsuario) {
    try {
        $conn = conectar();
        $sql = "SELECT ifnull(sum(puntos),0) puntuacion FROM resultados where idusuarios=:id";
        $st = $conn->prepare($sql);
        $st->execute(['id' => $idUsuario]);
        $fila = $st->fetch();
        return $fila['puntuacion'];
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }
}

function comprobarUsuario($nombre, $password) {
    try {
        $conn = conectar();
        //Buscamos un usuario con el nombre solicitado
        $sql = "select * from usuarios where nombre=:nombre";
        $st = $conn->prepare($sql);
        $st->execute(['nombre' => $nombre]);
        $usuario = $st->fetch();
        //Si no existe es un alta, lo insertamos en la BD
        if (!$usuario) {
            $st = $conn->prepare("insert into usuarios (nombre,password) values (:nombre,:password)");
            $st->execute(['nombre' => $nombre, 'password' => md5($password)]);
            //Y devolvemos el id del usuario insertado
            return $conn->lastInsertId();
        } else {
            //Si el usuario existe miramos si la contrasela coincide, si es así devolvemos el id
            if (md5($password) == $usuario['password']) {
                return $usuario['idusuarios'];
            }
        }
        //Si no se da ninguna de las condiciones devolvemos falso
        return false;
    } catch (Exception $ex) {
        echo $ex->getMessage();
        return false;
    }
}

function guardaResultado($idUsuario, $idPregunta, $puntos) {
    try {
        $conn = conectar();
        $sql = "insert into resultados (idusuarios,idpreguntas,puntos) values (:idu,:idp,:puntos)";
        $st = $conn->prepare($sql);
        $st->execute(['idu' => $idUsuario, 'idp' => $idPregunta, 'puntos' => $puntos]);
        return getPuntuacion($idUsuario);
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }
}

login.php

<?php
require_once 'libreria.php';
$error="";
session_start();
//Recuperamos el valor de nombre y password
$nombre= filter_input(INPUT_POST, 'nombre');
$password= filter_input(INPUT_POST, 'password');

//Si no están vacíos es porque hay un registro o login, lo comprobamos en la BD
if (!empty($nombre) && !empty($password)){
    //La función comprobar Usuario nos devuelve el id del usuario si existe
    $idUsuario=comprobarUsuario($nombre,$password);
    //Si existe el usuario guardamos la información en la BD y redirigimos al index
    if ($idUsuario){
        $_SESSION['idUsuario']=$idUsuario;
        $_SESSION['nombre']=$nombre;
        header("location:index.php");
    } else{
        $error="Usuario o contraseña incorrecta";
    }
}
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Trivial informático</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>

        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>

    </head>
    <body>
        <div class="container" >
            <div class="jumbotron">
            <h1>Introduce tu usuario y contraseña</h1>
            <h2>Si no estás en el sistema se creará tu usuario</h2>
            <h2 class="text-danger"><?=$error?></h2>
            </div>
            <form method="post">
                <div class="form-group">
                    <label for="nombre">Usuario:</label>
                    <input type="text" class="form-control" name="nombre">
                </div>
                <div class="form-group">
                    <label for="pwd">Password:</label>
                    <input type="password" class="form-control" name="password">
                </div>
                <button type="submit" class="btn btn-primary">Enviar</button>
            </form>
        </div>
    </body>
</html>

index.php

<?php
session_start();
//Si no está definida la variable de sesión es que no se ha logueado, lo mandamos al login
if (empty($_SESSION['idUsuario'])){
    header("location:login.php");
}
require_once("libreria.php");
//Recuperamos la puntuación para mostrarla
$puntuacion= getPuntuacion($_SESSION['idUsuario']);
?>
<!DOCTYPE html>

<html>
    <head>
        <title>Trivial informático</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>

        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
        
    </head>
    <body>
        <div class="container" >
            <div class="jumbotron">
                <h1 class="display-1">Trivial. Bienvenido <?=$_SESSION['nombre']?></h1>
                <p>¿Cual es tu cultura general? Puntuación: <span id="puntuacion"><?=$puntuacion?></span></p>
            </div>
            <div class="row">
                <div class="col-12" id="mensaje" style="min-height: 70px;"></div>
            </div>
            <div class="row tablero">
                <div class="col-12"><h1 id="pregunta" class="text-center">Bienvenido al trivial. Muy pronto preguntas</h1></div>
            </div>
            <div class="row my-4 tablero">

                <div class="col-6 text-center"><button id="res1" class="btn btn-lg btn-success">.</button></div>
                <div class="col-6 text-center"><button id="res2" class="btn btn-lg btn-success">.</button></div>

            </div>

            <div class="row tablero">

                <div class="col-6 text-center"><button id="res3" class="btn btn-lg btn-success">.</button></div>
                <div class="col-6 text-center"><button id="res4" class="btn btn-lg btn-success">.</button></div>

            </div>
        </div>
        <script src="trivial.js" type="text/javascript"></script>

    </body>
</html>

trivial.js

var preguntas;
//Busca una pregunta por Ajax
function cargarPregunta() {
    $.get("pregunta.php", function (datos, status) {

        if (status == "success") {
            preguntas = JSON.parse(datos);
            pintarPregunta();
        }
    });
}
//Pinta la pregunta en nuestro HTML
function pintarPregunta() {
    $('#pregunta').text(preguntas.pregunta);
    $('#res1').text(preguntas.respuestas[0]);
    $('#res2').text(preguntas.respuestas[1]);
    $('#res3').text(preguntas.respuestas[2]);
    $('#res4').text(preguntas.respuestas[3]);
    $(".tablero").show();
    $('#mensaje div').fadeOut();
}

$(function () {
    cargarPregunta();
    //Enlazar con los botones el evento click y comprobar si la respuesta es correcta
    $('button').click(function () {
        var puntos = 0;
        //Comprobamos que el botón pulsado es la respuesta correcta
        if ($(this).text() === preguntas.correcta) {
            $('#mensaje').html('<div class="alert alert-success alert-dismissible">  <button type="button" class="close" data-dismiss="alert">&times;</button>  <strong>¡Bien! </strong> Respuesta correcta.</div>')
            puntos = 1;
        } else {
            $('#mensaje').html('<div class="alert alert-danger alert-dismissible">  <button type="button" class="close" data-dismiss="alert">&times;</button>  <strong>¡Error! </strong> Respuesta incorrecta.</div>')

        }
        //Escondemos el tablero para queno pueda pulsar más botones
        $(".tablero").hide();
        //LLamamos por ajax con post para guardar los resultados, la función nos devuelve la puntuación
        $.post("resultado.php", {idPregunta: preguntas.id, puntos: puntos}, function (datos, status) {
            $('#puntuacion').text(datos);
            cargarPregunta();
        });

    });
});

pregunta.php

<?php

require_once 'libreria.php';
session_start();
//Obtenemos una pregunta de la base de datos
$fila = getPregunta($_SESSION['idUsuario']);

//La fila que recuperamos la organizamos de una manera más amigable para el JS
$res['pregunta'] = $fila['pregunta'];
$res['id'] = $fila['idpreguntas'];
$res['correcta'] = $fila['respuesta1'];
$res['respuestas'] = [$fila['respuesta1'], $fila['respuesta2'], $fila['respuesta3'], $fila['respuesta4']];
shuffle($res['respuestas']);

//Lo codificamos en JSON
echo json_encode($res);

resultado.php

<?php
require_once 'libreria.php';
session_start();
//Recuperamos los datos
$idUsuario= $_SESSION['idUsuario'];
$idPregunta= filter_input(INPUT_POST, 'idPregunta');
$puntos= filter_input(INPUT_POST, 'puntos');
//Y guardamos el resultado
$puntos=guardaResultado($idUsuario,$idPregunta,$puntos);
//Devolvemos los puntos
echo $puntos;

Trivial 2.0: Responder pregunta

Cuando el usuario pinche en un botón tendremos que averiguar si la respuesta es correcta y guardar el resultado de la acción en la base de datos. Es más sencillo de lo que parece. En primer lugar enlazamos el click de los botones por jQuery:

  $('button').click(function () {
....
}

Ahí tendremos que hacer dos cosas. Comprobar que la respuesta es correcta o no y mostrar un mensaje en consecuencia y guardar en la base de datos. Lo primero es simple:

 var puntos = 0;
        if ($(this).text() === preguntas.correcta) {
            $('#mensaje').html('<div class="alert alert-success alert-dismissible">  <button type="button" class="close" data-dismiss="alert">&times;</button>  <strong>¡Bien! </strong> Respuesta correcta.</div>')
            puntos = 1;
        } else {
            $('#mensaje').html('<div class="alert alert-danger alert-dismissible">  <button type="button" class="close" data-dismiss="alert">&times;</button>  <strong>¡Error! </strong> Respuesta incorrecta.</div>')

        }

Lo segundo, también:

$.post("resultado.php", {idPregunta: preguntas.id, puntos: puntos}, function (datos, status) {
            $('#puntuacion').text(datos);
            cargarPregunta();
        });

Todo junto:

 $('button').click(function () {
        var puntos = 0;
        //Comprobamos que el botón pulsado es la respuesta correcta
        if ($(this).text() === preguntas.correcta) {
            $('#mensaje').html('<div class="alert alert-success alert-dismissible">  <button type="button" class="close" data-dismiss="alert">&times;</button>  <strong>¡Bien! </strong> Respuesta correcta.</div>')
            puntos = 1;
        } else {
            $('#mensaje').html('<div class="alert alert-danger alert-dismissible">  <button type="button" class="close" data-dismiss="alert">&times;</button>  <strong>¡Error! </strong> Respuesta incorrecta.</div>')

        }
        //Escondemos el tablero para queno pueda pulsar más botones
        $(".tablero").hide();
        //LLamamos por ajax con post para guardar los resultados, la función nos devuelve la puntuación
        $.post("resultado.php", {idPregunta: preguntas.id, puntos: puntos}, function (datos, status) {
            $('#puntuacion').text(datos);
            cargarPregunta();
        });

    });

La página a la que llamamos se limita a guardar los datos y devolver la puntuación:

<?php
require_once 'libreria.php';
session_start();
//Recuperamos los datos
$idUsuario= $_SESSION['idUsuario'];
$idPregunta= filter_input(INPUT_POST, 'idPregunta');
$puntos= filter_input(INPUT_POST, 'puntos');
//Y guardamos el resultado
$puntos=guardaResultado($idUsuario,$idPregunta,$puntos);
//Devolvemos los puntos
echo $puntos;

Guardar resultado es un simple insert:

function guardaResultado($idUsuario, $idPregunta, $puntos) {
    try {
        $conn = conectar();
        $sql = "insert into resultados (idusuarios,idpreguntas,puntos) values (:idu,:idp,:puntos)";
        $st = $conn->prepare($sql);
        $st->execute(['idu' => $idUsuario, 'idp' => $idPregunta, 'puntos' => $puntos]);
        return getPuntuacion($idUsuario);
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }
}

Y obtener los resultados un simple sql:

function getPuntuacion($idUsuario) {
    try {
        $conn = conectar();
        $sql = "SELECT ifnull(sum(puntos),0) puntuacion FROM resultados where idusuarios=:id";
        $st = $conn->prepare($sql);
        $st->execute(['id' => $idUsuario]);
        $fila = $st->fetch();
        return $fila['puntuacion'];
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }
}

Trivial 2.0: Recuperar pregunta por ajax

Para recuperar las preguntas por ajax necesitamos tres cosas. Una llamada con ajax desde JS. Una página en PHP que busque la pregunta y la devuelva. Y, como somos ordenaditos, una función en la librería que busque la pregunta.

Empecemos por el JS, que se limita a pedir la pregunta:

var preguntas;
//Busca una pregunta por Ajax
function cargarPregunta() {
    $.get("pregunta.php", function (datos, status) {

        if (status == "success") {
            preguntas = JSON.parse(datos);
            pintarPregunta();
        }
    });
}
//Pinta la pregunta en nuestro HTML
function pintarPregunta() {
    $('#pregunta').text(preguntas.pregunta);
    $('#res1').text(preguntas.respuestas[0]);
    $('#res2').text(preguntas.respuestas[1]);
    $('#res3').text(preguntas.respuestas[2]);
    $('#res4').text(preguntas.respuestas[3]);
    $(".tablero").show();
    $('#mensaje div').fadeOut();
}

El backend en php, donde llama el ajax, es sólo un poco más complicado:

<?php

require_once 'libreria.php';
session_start();
//Obtenemos una pregunta de la base de datos
$fila = getPregunta($_SESSION['idUsuario']);

//La fila que recuperamos la organizamos de una manera más amigable para el JS
$res['pregunta'] = $fila['pregunta'];
$res['id'] = $fila['idpreguntas'];
$res['correcta'] = $fila['respuesta1'];
$res['respuestas'] = [$fila['respuesta1'], $fila['respuesta2'], $fila['respuesta3'], $fila['respuesta4']];
shuffle($res['respuestas']);

//Lo codificamos en JSON
echo json_encode($res);

Por último necesitamos en nuestra librería una función que nos busque una pregunta en la BD y nos la devuelva:

function getPregunta($idUsuario) {
    try {
        $conn = conectar();
        //Buscamos una pregunta que no se haya hecho a este usuario al azar
   $sql = "SELECT * FROM trivial.preguntas where idpreguntas not in (select idpreguntas from resultados where idusuarios=$idUsuario) order by rand() limit 1";
            $resul = $conn->query($sql);
        $fila = $resul->fetch();
        return $fila;
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }
}