You are on page 1of 41

CURSO DE PROGRAMACIN PARA CALCULADORA HP PRIME

1. INTRODUCCIN
El HP Prime es una calculadora grfica fabricado por Hewlett-Packard (HP). Contiene
caractersticas comunes en los telfonos inteligentes, con una pantalla tctil y
aplicaciones disponibles para poner en l. Hay dos lados en la calculadora, una pantalla
de inicio numrico y un sistema de lgebra computacional (CAS).
La calculadora HP Prime tambin dispone de su propio lenguaje de programacin que
puede utilizar para explorar y resolver problemas matemticos. El lenguaje de
programacin utilizado es el HP PPL.
1.1. CONOCIENDO LA CALCULADORA

#free style

1
NMERO FUNCIN
1 Pantalla tctil y LCD: 320 240 pxeles
2 Men de botones tctiles contextuales
3 Teclas de aplicaciones de HP
4 Configuracin de las preferencias y la vista de Inicio
5 Funciones matemticas y cientficas habituales
6 Teclas Alpha y Shift
7 Tecla de encendido, de cancelacin y de apagado
8 Catlogos de listas, matrices, programas y notas
9 Tecla de ltima respuesta (Ans)
10 Tecla de aceptacin (Intro)
11 Tecla de retroceso y eliminacin
12 Tecla de men (y pegado)
13 Tecla CAS (y preferencias de CAS)
14 Tecla de vista (y copiado)
15 Tecla de escape (y borrado)
16 Tecla Ayuda
17 Rueda basculante (para mover el cursor)

2. PROGRAMACIN EN HP PPL
2.1. CATLOGO DE PROGRAMAS
El catlogo de programas es donde se ejecutan y depuran los programas y se envan
a otra HP Prime. Tambin se puede cambiar el nombre de los programas o eliminarlos
y es donde se inicia el editor de programas. El editor de programa es donde se crean y
editan los programas. Tambin se pueden ejecutar programas desde Vista de inicio o
desde otros programas.
El nombre del programa solo puede contener caracteres alfanumricos (letras y
nmeros) y el carcter de subrayado. El primer carcter debe ser una letra.

2.2. CREACIN DE UN NUEVO PROGRAMA


Para crear un nuevo programa se sigue los siguientes pasos:
Abra el catlogo de programas e inicie un programa nuevo.

2
Introduzca un nombre para el nuevo programa.

Presione OK. Se crea automticamente una plantilla para el programa. La


plantilla consta
de un encabezado para una funcin del mismo nombre que el programa,
EXPORT MYPROGRAM (), y un par BEGINEND; que encerrar las
instrucciones de la funcin.

2.3. LENGUAJE DE PROGRAMACIN DE LA CALCULADORA HP PRIME


El lenguaje de programacin de HP Prime le permite extender el potencial de HP Prime
agregando programas, funciones y variables al sistema. Los programas que escriba
pueden ser independientes o estar adjuntados a una aplicacin. Las funciones y las
variables que cree pueden ser locales o globales. Si estn se consideran global,
aparecen en el men del usuario.
2.4. ESTRUCTURA DE PROGRAMAS
La estructura de un programa siempre est encerrada por EXPORT BEGIN END.

3
3. VARIABLES Y OBJETOS
3.1. VARIABLES
Son valores asignados en la memoria con un nombre dentro de un programa que se
requieren constantemente para ser operados.
Las variables en un programa de HP Prime pueden utilizarse para almacenar nmeros,
listas, matrices, grficos, cadenas y expresiones.
3.1.1. VARIABLES GLOBALES
Son aquellas que se declaran en un programa y pueden ser reconocidos en cualquier
momento (es decir, visible en cualquier lugar de la calculadora). Estos variables se
clasifican en los siguientes tipos:
Variables de inicio: Son las variables que poseen nombres reservados, es decir ya
tienen un espacio reservado en la memoria. Estos variables son:
Reales

Compleja

Lista

4
Matriz

Grficas

Configuracin

Sistema

5
Variables del cas (sistema algebraico computacional): Son las variables que se
utilizan para el sistema algebraico. Estos tipos de variables son creadas por el usuario
y no tienen ningn tipo en particular.

Variables de aplicacin: Son las variables que se utilizan para almacenar datos en
las aplicaciones o para cambiar la configuracin de la aplicacin. Poseen nombres
reservados y no pueden ser creados por el usuario.

Variables de usuario: Son variables creadas explcitamente por el usuario. Puede


crear variables de usuario en un programa o por asignacin en la Vista de inicio. Las
variables de usuario creadas por asignacin o exportadas desde un programa
aparecern en el men de usuario Vars.

3.1.2. VARIABLES LOCALES


Son las que solo se ejecuta en un programa y solo son reconocidos dentro de ste.
Estas variables son almacenadas en la memoria temporal durante la ejecucin de un
programa. Esta forma de almacenar es recomendable ya que utiliza menos memoria.
Se declara 8 variables como mximo por cada lnea.

6
3.2. OBJETOS
Son valores asignados en una variable para ser operados dentro de un programa.
3.2.1. TIPOS DE OBJETOS
0: Real
1: Entero
2: Cadena
3: Compleja
4: Matriz
5: Error
6: Lista
8: Funcin
9: Unidad

4. COMANDOS DE PROGRAMA
4.1. COMANDOS DEL MENU Plant.
4.1.1. BLOQUE
Los comandos de bloque determinan el comienzo y el final de una subrutina o funcin.
BEGIN END: Define un comando o el conjunto de comandos que deben ejecutarse
juntos en un programa.
Sintaxis: BEGIN command1; command2; ...; commandN; END;

7
RETURN: Devuelve el valor actual de la expresin. Si existe una expresin despus de
RETURN, ya no se ejecuta.
Sintaxis: RETURN expresin;

KILL: Detiene la ejecucin del programa actual (con depuracin).


Sintaxis: KILL;

4.1.2. BIFURCACIN
IF THEN: Evala prueba. Si prueba es verdadero (distinto de 0), ejecuta comandos. De
lo contrario, no sucede nada.
Sintaxis: IF prueba THEN comandos END;

IF THEN ELSE: Evala prueba. Si prueba es verdadero (distinto de 0), ejecuta


comandos 1, de lo contrario, ejecuta comandos.

8
Sintaxis: IF prueba THEN comandos 1 ELSE comandos 2 END;

CASE: Evala prueba1. Si es verdadero, ejecuta comandos1 y cierra el CASE. De lo


contrario, evala prueba2. Si es verdadero, ejecuta comandos2 y cierra el CASE.
Contina evaluando pruebas hasta que encuentra una verdadera. Si no encuentra
ninguna prueba verdadera, ejecuta los comandos predeterminados, si se proporcionan.
El comando CASE se limita a 127 bifurcaciones.
Sintaxis:
CASE
IF prueba1 THEN comandos1 END;
IF prueba2 THEN comandos2 END;

[ DEFAULT comandos]
END;

IFERR: Ejecuta la secuencia de comandos1. Si se produce un error durante la


ejecucin de comandos1, ejecuta la secuencia de comandos2.
Sintaxis:
IFERR comandos1 THEN comandos2 END;

9
IFERR ELSE: Ejecuta la secuencia de comandos1. Si se produce un error durante la
ejecucin de commands1, ejecuta la secuencia de commands2. De lo contrario, ejecuta
la secuencia de comandos3.
IFERR comandos1 THEN comandos2 ELSE comandos3 END;

EJEMPLO 01.

Clculo del centro de gravedad en secciones tipo T.

Datos:

b = 45cm bw = 5cm h = 53cm hf = 5cm

10
DIAGRAMA DE FLUJO.

INICIO

b, bw , h, h f

Area bh f b w h h f

b
h f b h h
2
b
f
2
X C 2 w
A

h f
hf
h bh h b h h
f 2 w f
2
YC
A

A, X C ,YC

FIN

CDIGO DEL PROGRAMA.

EJECUCIN DEL PROGRAMA.

11
EJEMPLO 02.

Clculo de tipo de flujo en tuberas.

Datos:

Q = 0.1 m3/s

D = 10 pulg.

= 1.14*10^-6 m2/s
4Q
Re
D
Re 2100 FLUJO LAMINAR
2100 Re 4100 FLUJO EN TRANSICION
Re 4100 FLUJO TUEBULENTO

DIAGRAMA DE FLUJO.

INICIO

Q, D,

4Q
Re
D

NO Re 2100 NO
Re 2100 Y TIPO " F .TURBULENTO "
Re 4100
SI
TIPO " F .LAMINAR "

SI
TIPO " F.TRANSICION "
FIN Re,TIPO

12
CDIGO DEL PROGRAMA.

EJECUCIN DEL PROGRAMA.

Ahora resolvemos el mismo ejemplo utilizando CASE.

DIAGRAMA DE FLUJO.

INICIO

Q, D,

4Q
Re
D

13
A

SI
Re 2100 TIPO " F .LAMINAR "

NO

Re 2100 SI

Y TIPO " F.TRANSICION "


Re 4100

NO
TIPO " F .TURBULENTO "

Re,TIPO

FIN

CDIGO DEL PROGRAMA.

14
EJECUCIN DEL PROGRAMA.

4.1.3. BUCLE
FOR: Define la variable var con el valor de inicio y siempre que el valor de esta variable
sea inferior o igual a fin, ejecuta la secuencia de comandos, y luego incremente 1 a la
variable.
Sintaxis: FOR var FROM inicio TO fin DO comandos END;

FOR STEP: Define la variable var con el valor inicio y siempre que el valor de esta
variable sea inferior o igual a fin ejecuta la secuencia de comandos y luego suma
incremento a var.
Sintaxis: FOR var FROM inicio TO fin [STEP incremento] DO comandos END;

FOR DOWN: Define la variable var con el valor inicio y siempre que el valor de esta
variable sea mayor o igual a fin, ejecuta la secuencia de comandos, y luego resta 1
(decremento) a var.
Sintaxis: FOR var FROM inico DOWNTO fin DO comandos END;

15
FOR STEP DOWN: Define la variable var con el valor inicio y siempre que el valor de
esta variable sea mayor o igual a fin ejecuta la secuencia de comandos y luego resta
decremento a var.
Sintaxis: FOR var FROM inicio DOWNTO fin [STEP incremento] DO comandos END;

WHILE: Evala prueba. Si el resultado es verdadero (distinto de 0), ejecuta los


comandos y repite. Es decir, repite mientras el test sea verdadero.
Sintaxis: WHILE prueba DO comandos END;

REPEAT: Repite la secuencia de comandos hasta que el valor de test sea verdadero
(distinto de 0). Es decir, repite mientras el test sea falso.
Sintaxis: REPEAT comandos UNTIL prueba ;

16
BREAK: Sale del comando de bucles rompiendo n niveles de bucle. La ejecucin
retoma en la primera instruccin despus del bucle. Sin un argumento, sale desde un
nico bucle.
Sintaxis: BREAK(n);

4.1.4. VARIABLE
LOCAL: Hace que las variables var1, var2, etc., sean locales para el programa en el
que se encuentran.
Sintaxis: LOCAL var1, var2, varn; (8 variables mximo).
EXPORT: Exporta las variables var1, var2, etc., por lo que se encuentran disponibles
globalmente.
Sintaxis: EXPORT var1, [var2, , varn];
o bien

17
EXPORT var1: =val1, [var2: =val2, varn: =valn];

4.1.5. FUNCIN
EXPORT: En un programa, declara las funciones o variables para exportar
globalmente. Las funciones exportadas aparecen en el men de Caja de herramientas
de usuario y las variables exportadas aparecen en los mens Variables del sistema
algebraico computacional, Aplicacin y Usuario.
Sintaxis: EXPORT Nombre de la funcin(Parmetros)
BEGIN
Definicin de la funcin;
END;

EJEMPLO 03
Ajustar los siguientes datos a un polgono de 2do grado, por el mtodo de mnimos
cuadrados. m=10.
X 1 2 3 4 5 6 7 8 9 10
Y 133.198 103.894 103.224 133.198 74.974 71.38 82.294 71.566 70.647 130.106

Sea una serie de datos (X, Y) y m el nmero de datos. Entonces:


Y = aO + a1 X + a2 X 2
Donde

r m l r l
aO
a =
a
I I

18
DIAGRAMA DE FLUJO
INICIO

X ,Y

m Nmero ( X , Y )
SX 0, SX 2 0, SX 3 0, SX 4 0
SY 0, SYX 0, SYX 2 0

i 1

NO
i m
SI
SX SX X , SX 2 SX 2 X 2
i i
SX 3 SX 3 X 3 , SX 4 SX 4 X 4
i i

SY SY Yi , SYX SYX Yi X i
SYX 2 SYX 2 Y X 2
i i

i i 1

m SX SX 2 SY

A SX SX 2 SX 3 , B SYX

SX 2 SX 3 SX 4 SYX 2

a0
1

a1 A B
a 2

Y a0 a1 X a 2 X 2

FIN

19
CDIGO DEL PROGRAMA

EJECUCIN DEL PROGRAMA.

EJEMPLO 04
Clculo de coeficiente de friccin en tuberas por la ecuacin de Colebrook-White.
Datos:
Q = 0.1 m3/s
D = 10 pulg.
Ks = 0.00006m.
= 1.14*10^-6 m2/s
4Q
Re =
rr D

20
1 Ks 2.51
= -2Log1O ( + )
/f 3.7D Re/f

DIAGRAMA DE FLUJO.

INICIO

Q, D, K S ,

4Q
Re
D

SI
Re 2100 f1
64
Re

NO
f 0 0.001

0.25
f1 K 2
Log S 2.51
3.7D Re f
0

error f1 f 0

f 0 f1

NO
error 0.0000001

SI

Re, f1

FIN

21
CDIGO DEL PROGRAMA

EJECUCIN DEL PROGRAMA

4.2. COMANDOS DEL MENU Cmds


4.2.1. ENTRADA/SALIDA
Los comandos E/S se utilizan para ingresar datos en un programa y para generar datos
de salida desde un programa. Permite al usuario interactuar con los programas.
CHOOSE: Es un cuadro de eleccin con ttulo y conteniendo los elementos que elija.
Si el usuario selecciona un objeto, las variables cuyos nombres se proporcionen se
actualizarn para contener el nmero del objeto seleccionado (un nmero entero, 1, 2,
3, ...) o 0 si el usuario pulsa cancel.
Sintaxis: CHOOSE(var, "ttulo", {"elemento1", "elemento2",,"elementon"})

22
EDITLIST: Inicia el Editor de lista cargando listvar y muestra la lista especificada. Si se
utiliza en programacin, retorna al programa cuando el usuario pulsa OK.
Sintaxis: EDITLIST (listvar, [Titulo], [Solo lectura]).
[Titulo]: Titulo o {Titulo, {Nombre de fila}, {Nombre de columna}}
[Solo lectura]: Si Solo lectura es 1, no se podr modificar.

EDITMAT: Inicia el Editor de matriz y muestra la matriz especificada. Si se utiliza en


programacin, retorna al programa cuando el usuario pulsa OK.
Sintaxis: EDITMAT(matrizvar)
[Titulo]: Titulo o {Titulo, {Nombre de fila}, {Nombre de columna}}
[Solo lectura]: Si Solo lectura es 1, no se podr modificar.

23
GETKEY: Devuelve el ID (identificador) de la primera tecla en el bfer del teclado, o
1 si no se puls ninguna tecla desde la ltima llamada a GETKEY. Los ID de tecla son
enteros de 0 a 50, numerados desde la esquina superior izquierda (tecla 0) a la esquina
inferior derecha (tecla 50) como se muestra en la figura.
Sintaxis: GETKEY

24
INPUT: La forma ms sencilla de este comando abre un cuadro de dilogo con el ttulo
dado y un campo denominado etiqueta, y muestra el contenido de ayuda en la parte
inferior. El cuadro de dilogo incluye las teclas de men CANCEL y OK. El usuario
puede ingresar un valor en el campo etiquetado. Si el usuario presiona la tecla de men
OK, la variable var se actualiza con el valor introducido y el comando devuelve 1. Si el
usuario presiona la tecla de men CANCEL, la variable no se actualiza y devuelve 0.
Sintaxis: INPUT(var, [ttulo] , [etiqueta], [ayuda] , [restablecer_valor] , [valor_inicial])
Sintaxis: INPUT({vars}, [ttulo], [{etiquetas}], [{ayuda}], [{restablecer_valores}],
[{valores_iniciales}]).
{vars}: {nombre var, tipo, {pos}}.
{pos}: {inicio de campo en %, ancho de campo en %, lnea de control (inicia en 0)}
Existe un mximo de siete lneas de controles (0 a 6) por pgina.

25
ISKEYDOWN: Devuelve true (verdadero) (distinto de cero) si la tecla cuyo id_tecla se
proporciona est presionada actualmente y falso (0) si no es as.
Sintaxis: ISKEYDOWN(id_tecla);

MOUSE: Devuelve dos listas que describen la ubicacin actual de cada puntero posible
(listas vacas si no se utilizan punteros). La salida es {x, y, z original, y original, tipo}
donde tipo es 0 (para nuevo), 1 (para completado), 2 (para arrastrar), 3 (para alargar),
4 (para girar) y 5 (para un clic largo).
Sintaxis: MOUSE[(ndice)]

26
MSGBOX: Muestra un cuadro de mensaje con el valor de la expresin o cadena dada.
Sintaxis: MSGBOX (expresin o cadena [ ,ok_cancel?]);
Si ok_cancel? es 1, entonces muestra dos opcines OK y Cancel.
Si ok_cancel? es 0, entonces muestra una sola opcin OK.

PRINT: Imprime el resultado de expresin o cadena en el terminal.


PRINT sin ningn argumento borra el terminal.
Sintaxis: PRINT (expresin o cadena);

27
WAIT: Pausa la ejecucin del programa durante n segundos. Con ningn argumento o
con n = 0, pausa la ejecucin durante un minuto.
Sintaxis: WAIT(n);
Si n=-1, pausa la ejecucin hasta que se pulsa una tecla o exista una actividad del
mouse, devolviendo el cdigo de la tecla o una lista de la forma {tipo, x, y, dx, dy}.
Donde:
x, y: es la posicin del evento.
tipo: es el tipo de actividad.
0: mouse hacia abajo
1: movimiento del mouse
2: muse hacia arriba
3. Clic del mouse
5: estiramiento del mouse
6: rotacin del mouse
7: clic largo del mouse

28
EJEMPLO 05
Utilizaremos el mismo cdigo del ejemplo 03, para desarrollar una entrada con tabla.
DATOS:
X 1 2 3 4 5 6 7 8 9 10
Y 133.198 103.894 103.224 133.198 74.974 71.38 82.294 71.566 70.647 130.106

CDIGO DEL PROGRAMA

29
EJECUCIN DEL PROGRAMA

EJEMPLO 06
Utilizaremos el mismo cdigo del ejemplo 04, para desarrollar una entrada con
formulario.
Datos:
Q = 0.1 m3/s D = 10 pulg.
Ks = 0.00006m = 1.14*10^-6 m2/s
CDIGO DEL PROGRAMA

EJECUCIN DEL PROGRAMA

ruybor@hotmail.com Cel.: 999195613 RPM: #999195613

30
4.2.2. CADENAS
ASC: Devuelve una lista que contiene los cdigos ASCII de cadena.
Sintaxis: ASC (cadena)

LOWER: Convierte caracteres de maysculos a una cadena en minsculas.


Sintaxis: LOWER (cadena)

UPPER: Convierte caracteres de minsculas a una cadena en maysculas.


Sintaxis: UPPER (cadena)

CHAR: Devuelve la cadena correspondiente a los cdigos de carcter.


Sintaxis: CHAR (entero o vector)

DIM: Devuelve la cantidad de caracteres en cadena.

31
Sintaxis: DIM (cadena)

STRING: Evala la expresin y devuelve el resultado como una cadena. Los


parmetros adicionales especifican cmo se muestran los nmeros.
Si se especifica el Modo, debe ser:
0: Utilice la configuracin actual
1: Estndar
2: Fijo
3: Cientfico
4: Ingeniera
5: Flotante
6: Redondeo
7: Fraccin
La precisin es -1 para la configuracin actual o de 0 a 12.
Sintaxis: STRING (Expresin, [Modo], [Precisin])

MID: Extrae n caracteres de la cadena delimitado por el ndice de pos. n es opcional, y


si no se especifica extrae todos los caracteres restantes de la cadena.
Sintaxis: MID (cadena, pos, [n])

32
REPLACE: Reemplaza parte del objeto1 con el objeto2 comenzando en el inicio. Los
objetos pueden ser matrices, vectores o cadenas.
Sintaxis: REPLACE (objeto1, inicio, objeto2)

4.2.3. MATRIZ
ADDCOL: Inserta los valores de un vector en una nueva columna insertada en el
nmero de columna especificada. El nmero de valores en el vector debe ser igual a la
cantidad de filas de la matriz.
Sintaxis: ADDCOL(matriz, vector, nmero_columna)

ADDROW: Inserta los valores de un vector en una nueva fila insertada en el nmero
de fila especificada. El nmero de valores en el vector debe ser igual al nmero de
columnas de la matriz.
Sintaxis: ADDROW(matriz, vector, nmero_fila)

DELCOL: Elimina la columna especificada de la matriz.


Sintaxis: DELCOL(nombre, nmero_columna)

33
DELROW: Elimina la fila especificada de la matriz.
Sintaxis: DELROW(nombre ,nmero_fila)

REDIM: Redimensiona la matriz o vector especificado. Para una matriz, tamao es una
lista de dos nmeros enteros {n1, n2}. Para un vector, tamao es una lista que contiene
un nmero entero {n}. Se mantienen los valores existentes en la matriz. El valor de
relleno ser 0.
Sintaxis: REDIM(nombre, tamao)

REPLACE: Reemplaza parte de una matriz o vector almacenado en matriz con un


objeto comenzando por la posicin de inicio. El inicio para una matriz es una lista que
contiene dos nmeros; para un vector, es un nico nmero.
Sintaxis: REPLACE(nombre, inicio, objeto)

34
SCALE: Multiplica el nmero de fila de la matriz especificada por un valor.
Sintaxis: SCALE(nombre, valor, nmero_fila)

SCALEADD: Multiplica fila1 de la matriz por el valor y a continuacin, suma este


resultado a la fila2 de la matriz y sustituye fila2 por el resultado.
Sintaxis: SCALEADD(nombre, valor, fila1, fila2)

SUB: Extrae una parte de una matriz, vector, lista grfico. Inicio y fin se especifican
por medio de una lista de dos nmeros para una matriz, un nmero para un vector o
para listas, o un par ordenado, (X, Y) para grfico.
Sintaxis: SUB(objeto, inicio, final)

SWAPCOL: Intercambia columna1 y columna2 en la matriz especificada.


Sintaxis: SWAPCOL(nombre, columna1, columna2)

35
SWAPROW: Intercambia fila1 y fila2 en la matriz especificada.
Sintaxis: SWAPROW(nombre, fila1, fila2)

MAKEMAT: Crea una matriz o vector de objetos con filas y columnas especificadas.
Sintaxis: MAKEMAT (objeto, fila, columna)

EJEMPLO 07
Interpolar los siguientes datos mediante una spline cbica:
X 2 3 5
Y 1 2 7
Solucin:
Definimos un polinomio cbico en cada uno de los intervalos que se forman:

36
DIAGRAMA DE FLUJO

INICIO

X ,Y

NP Nmero( X , Y )
NT NP 1

i 1

NO
i NT A

SI
j 1

NO
j NT

SI

i j NO

SI
A X 3
2i1,4 j3 i

A2i1,4 j2 X i2
A2i1,4 j1 X i
A2i1,4 j 1
A2i,4 j 3 X i1
3

A2i,4 j 2 X i1
2

A2i,4 j 1 X i1
A2i,4 j 1

j j 1

37
A

i 1

NO
i NT 1 B

SI
j 1

NO
j NT

SI

i j NO

SI

A2 NT i,4 j 3 3X i1
2

A2 NT i,4 j 2 2 X i1
A2 NT i,4 j 1 1
A2 NT NP2i,4 j3 6 X i1
A2 NT NP2i,4 j2 2

NO
i 1 j

SI

A2 NT i,4 j3 3X i1
2

A2 NT i,4 j2 2 X i1
A2 NT i,4 j1 1
A2 NT NP2i,4 j3 6 X i1
A2 NT NP2i,4 j2 2

j j 1

38
B

A2( NT NP2)1,1 6 X 1
A2( NT NP2)1,2 2
A2( NT NP2)2,4 NT 3 6 X NP
A2( NT NP2)2,4 NT 2 2

i 1

NO
i NT

SI

B2i1,1 Yi
B2i,1 Yi1

i i 1

C A1 B

i 1

NO
i NT FIN

SI
Yi C4i3,1 X C4i2,1 X 2 C4i1,1 X C 4i,1
3

i i 1

39
CDIGO DEL PROGRAMA

40
EJECUCIN DEL PROGRAMA

41

You might also like