TIM ja GeoGebra
Tässä ohjeessa kerrotaan miten GeoGebraa käytetään TIMissä. Itse GeoGebra on niin laaja ohjelmisto, että sen käyttö on opeteltava erikseen.
TIMin GeoGebra-komponentti korvaa "vanhan" tavan, jossa vain upotettiin GeoGebra-tehtävä TIMin sisälle. TIMin GeoGebra-komponentin etuja on:
- tehtäviä voidaan tehdä ja säilyttää TIMIssä, jolloin ne varmasti aina löytyvät ja niihin on oikeus niillä, joilla on oikeus muokata dokumenttia
- opettaja voi seurata mitä opiskelijat ovat tehneet tehtävissä
- tehtävistä voidaan antaa pisteitä
Mitä syvällisemmin ominaisuuksia käytetään, sitä enemmän vaaditaan GeoGebran osaamista ja osin myös JavaScript-ohjelmointitaitoa. Jos tyydytään pelkkään tehtävän näyttämiseen, on käyttäminen silloin helppoa.
Alla pikainen esimerkki jossa käytetään valmista GeoGebra-tehtävää (j2axjgdc
) ja pyydettään käyttäjää säätämään keskuskulman arvoa. Säädetty kulma α
ja sitä vastaava kehän piste C
välitettään TIMille tallennettavaksi. TIM tarkistaa kulman ja antaa 1p, jos se on oikein. Käyttäjä ja opettaja voi selata vastauksia ja katsoa mihin piste C
on siirretty. Raporttiin tulostuu kulman nimi ja arvo.
``` {plugin="csPlugin" #geo60}
type: geogebra
stem: 'Säädä keskuskulma 60 asteeksi ja paina Tallenna'
-pointsRule:
expectCodePlain: "α = 60°"
width: 650
height: 430
material_id: "j2axjgdc"
javascript: |!!
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
timgeo.setPointsCoords(api, geostate.userpts); // käyttäjän pisteiden paikat
}
P.getData = function(){
return {
"usercode": ggbApplet.getValueString('α'), // kulma tutkittavaksi
"userpts": timgeo.getObjValue(ggbApplet,"C"), // piste C talteen
};
}
!!
```
Pohjan GeoGebra-tehtävälle löytää editorin Plugins/Others
-välilehdeltä.
Jos et jaksa lukea koko ohjetta ja sinulla on kiire, niin loikkaa suoraan esimerkkiin jossa tallennetaan 3:n pisteen tila.
vesal: En ole GeoGebran ammattilainen, niin toivon että ne jotka osaavat enemmän, korjaavat tätä ohjetta GeoGebran osalta. Painovirheitä saa korjata jokainen joka niitä huomaa :-)
1. Muutoksia GeoGebran oikeuksissa
GeoGebran on muuttanut miten sisältöä voi upottaa koodiin. Tämä aiheuttaa sen että vanhat tyyliin:
``` {plugin="showVideo"}
iframe: true
videoicon: false
hidetext: Piilota GeoGebra
type: small
videoname: "GeoGebra: Karteesinen koordinaatisto"
width: 650
height: 500
file: "https://www.geogebra.org/material/iframe/id/k2hefjk9/width/650/height/500/border/888888/rc/false/ai/false/sdz/true/smb/false/stb/false/stbh/true/ld/false/sri/true/at/auto"
```
olevat upotukset eivät enää toimi esimerkiksi iPadillä. Niiden tilalle pitää kirjoittaa
``` {plugin="csPlugin" #geo2taso}
type: geogebra
lazy: true
beforeOpen: "md:[GeoGebra: Karteesinen koordinaatisto](#)"
borders: false
norun: true
width: 650
height: 500
material_id: "k2hefjk9"
```
tai jos halutaan painike, josta tehtävä aukeaa:
``` {plugin="csPlugin" #geo4}
type: geogebra
open: false
lazy: false
showButton: GeoGebra: Karteesinen koordinaatisto
width: 650
height: 500
material_id: "k2hefjk9"
```
2. Tapoja käyttää
TIMissä GeoGebraa voi käyttää useilla eri tavoilla:
- upotettuna sisältönä
- lainataan GeoGebran palvelimelle tallennettu tehtävä sen tunnuksen perusteella
- käytetään
ggb
-tiedostoa - käytetään
xml
-tiedostoa - luodaan tehtävä GeoGebran komennoilla
- luodaan tehtävä GeoGebran JavaScript-Api-komennoilla
- melkein mikä vaan edellisten yhdistelmä
Kussakin käyttötavassa on omat hyvät ja omat huonot puolensa. Seuraavana annetaan esimerkkejä kustakin, kerrotaan miten tapaa käytetään ja mitkä ovat sen hyvät ja huonot puolet.
TIMissä tehtävät esitetään YAML-muotoisena tekstinä. Esimerkeistä käy ilmi käytetty YAML-muoto, mutta siitä voi lukea lisää myös erillisestä dokumentista:
Esimerkkien YAML-kieli näkyy myös kun avaa esimerkin vasemmalta puolelta edit-menun ja ottaa sieltä View source
.
2.1 Upotettu sisältö
Tämä tapa ei enää toimi iPadillä, joten vältä tätä!
Upotettu sisältö lähtee siitä, että tehtävä on tehty GeoGebran palvelimelle ja se ajetaan sieltä TIMiin upotettuna sisältönä:
Tällainen tehtävä saadaan tehtyä kun upotetun sisällön plugin muokataan seuraavasti:
``` {#geo1 plugin="showVideo"}
iframe: true
videoicon: false
hidetext: Piilota GeoGebra
type: small
videoname: "GeoGebra: Paraabelin polttopiste ja johtosuora. Klikkaa tehtävä tästä auki."
width: 650
height: 500
file: "https://www.geogebra.org/material/iframe/id/X8EFduVc"
```
Tehtävä on oletuksena kiinni niin, että se pitää avata klikkaamalla. Mikäli tehtävä halutaan aukeavan automaattisesti, voidaa sen tehdä lisäämällä koodiin attribuutti:
open: true
Osoitteessa oleva tunniste X8EFduVc
saadaan esimerkiksi GeoGebran sivun osoiteriviltä kun tehtävää (activity) muokataan GeoGebrassa.
Plussia
- Helppo käyttää
Miinuksia
- Tehtävää ei voi muokata, jos ei omista tehtävän oikeuksia
- Ei pysty seuraamaan mitä opiskelijat tekevät tehtävässä
- Ei pysty pisteyttämään opiskelijoiden toimintaa
- Tehtävä muuttuu TIMissä jos alkuperäistä muutetaan (voi olla myös plus)
Tämä käyttötapa sopiikin parhaiten silloin, kun GeoGebraa käytetään vain havaintovälineenä. Yleensä tehtävän perään kannattaa silloin laittaa jokin toinen TIMin tehtävä, kuten monivalinta tai avoin kysymys, jolla selvitetään onko opiskelija tehnyt tehtävässä tarkoitetut havainnot.
3. TIMin GeoGebra-komponentti viittaamalla tunnisteeseen
Edellistä vastaava toiminto saadaan TIMin csPlugin
-komponentilla kun laitetaan sen tyypiksi geogebra
:
Tämä saadaan koodilla:
``` {plugin="csPlugin" #geo2}
type: geogebra
borders: false
norun: true
width: 650
height: 500
material_id: "X8EFduVc"
```
Tässä tunniste (id) on selvitetty kuten edelläkin. Attribuuttien merkitykset:
borders
: kun false, jätetään pois TIM tehtäville tyypilliset reunukset (oletus true). Raameja ei ehkä kannata piilottaa jos tehtävässä on Tallenna-painike.norun
: piilotetaan tallennuspainike (oletus false, eli painike näytetään)width
: tehtävalueen leveysheight
: tehtäväalueen korkeysmaterial_id:
tehtävän tunniste GeoGebrassa
Plussia:
- helppo käyttää
- laajentamalla tulee paljon mahdollisuuksia
Miinuksia:
- tämmöisenään lataantuu automaattisesti, mikä ei ole hyvä isoissa dokumenteissa. Tähän on lääkkeitä myöhemmin
- tämmöisenään ei voi seurata käyttäjän toimia eikä arvostella. Näihin ohjeita myöhemmin.
- muokkaus edelleen vain GeoGebran kautta tehtävän omistajan toimesta
3.1 Pienin määrä attribuutteja
Kun attribuutit karsitaan minimiin, eli:
``` {plugin="csPlugin" #geo3}
type: geogebra
material_id: "X8EFduVc"
```
saadaan seuraava tulos:
Edelliseen verrattuna tässä on se ero, että on tallennuspainike ja raamit ja koko tulee oletuksilla (800 x 450). Kokoa joutuu kuitenkin usein säätämään sen mukaan, miten tehtävän saa mahtumaan.
4. Ei automaattista avaamista
Upotuksen oletusasetuksiin verrattuna on se ero, että tehtävät latautuvat näyttöön automaattisesti. Tässä on se vika, että jos isossa dokumentissa on paljon tehtäviä, menee niiden automaattisessa aukaisemisessa kauan aikaa.
Tähän on muutama ratkaisu
- avaaminen erillisestä painikkeeta
- laiska lataaminen
Huomattakoon että kaikki mitä tässä alaluvussa sanotaa, toimii myös muille GeoGebran käyttötavoille kuin material-id
:hen perustuviin.
4.1 Avaaminen painikkeesta
``` {plugin="csPlugin" #geo4}
type: geogebra
material_id: "X8EFduVc"
open: false
lazy: false
showButton: Tutki paraabelin johtosuoraa
```
jolla saadaan painike
Tehtävä aukeaa vasta painiketta painamalla ja näin isokaan dokumentti ei hidastu, vaikka siinä olisi kymmeniä tai satoja GeoGebra-komponentteja. Haittana on että käyttäjä joutuu avaamaan tehtävät erikseen ja ei näe mitä on tulossa.
4.2 Sulkeminen painikkeesta
Lisäämällä hideButton
saadaan lisäksi piilotuspainike:
``` {plugin="csPlugin" #geo4}
type: geogebra
material_id: "X8EFduVc"
open: false
lazy: false
showButton: Tutki paraabelin johtosuoraa
hideButton: Piilota
```
Lopputulos
4.3 Esikatselukuva
Tehtävään voidaan liittää esimerkiksi ruutukaappauskuva tehtävästä, joka näytetään ennenkuin tehtävä aukeaa. Ruutukaappauksen ottamisesta ja lisäämisestä on enemmän varsinaisessa TIMin käyttöohjeessa.
Tällöin esimerkiksi koodilla
``` {plugin="csPlugin" #geo5}
type: geogebra
beforeOpen: "md:![](/images/188561/image.png)"
open: false
lazy: false
borders: false
width: 650
height: 500
material_id: "X8EFduVc"
```
saataisiin tehtävä:
4.4 Laiska lataaminen
Tehtävä voidaan myös asettaa lataantumaan laiskasti. Itse asiassa, jos dokumentissa on paljon (kymmeniä) tehtäviä, ne lataantuvat automaattisesti laiskasti.
Laiskuus voidaan pakottaa attribuutilla lazy
ja siinä voidaan käyttää myös esikatselukuvaa:
``` {plugin="csPlugin" #geo6}
type: geogebra
beforeOpen: "md:![](/images/188561/image.png)"
lazy: true
borders: false
width: 650
height: 500
material_id: "X8EFduVc"
```
Tämä näyttää seuraavalle ja aukeaa, kun hiiren kuljettaa tehtävän päälle:
4.5 Ilmoitusteksti laiskasta lataamisesta
Attribuuttiin beforeOpen
voidaan kirjoittaa myös mitä tahansa muuta TIM-koodia, esimerkiksi pelkkää tekstiä, joka näkyy ennen tehtävän lataantumista.
4.6 Älä käytä yhdessä laiskaa lataamista ja erikseen avaamista
Ei ehkä kannata laittaa molemia ominaisuuksia kerralla. Eli jos on laiska lataaminen ja vielä erikseen open: false
, niin silloin käyttäjä joutuu ensin viemään kursorin tehtävän päälle ja sitten tulee vasta se painike ja sitten painamaan sitä.
Koska pitkissä dokumenteissa laiskuus tulee automaattisesti, kannattaa ehkä lisätä jokaiseen tehtävään, jossa on open: false
, myös
lazy: false
jotta molemmat eivät ole yhtäaikaa.
5. Oletustallentaminen
Kun ei ole attribuuttia:
norun: true
tai se on false
arvossa, tulee automaattisesti näkyviin Tallenna
-painike. Sen tekstiä voi tarvittasessa muuttaa attribuutilla:
button: "Kokeile ja tallenna tilanne välillä"
Jos ei tehdä mitään muuta, tallentuu käyttäjän tilanne ggb
-muodossa joka kerta, kun hän painaa Tallenna
-painiketta. Opettaja voi Teacher
-näkymästä katsella opiskelijoiden vastauksia ja pisteyttää niitä käsin. Jatkossa kerrotaan, miten voidaan pisteyttää automaattisesti.
Oletustallennuksen vika on se, että ggb on ISO ja tallennetaan joka kerta koko GeoGebra-tehtävän sisältö. Jos alkuperäistä tehtävää muutetaan, niin vastauksista tämä ei näy ja kukin opiskelijan uusi vastaus perustuu hänen edelliseen vastaukseensa (ellei erikseen aloita alusta).
Myöhemmin esitetään muita tallennusvaihtoehtoja, jotka tosin ovat hieman työläämpiä ja pitää tehdä erikseen jokaiselle tehtävälle.
Tallentamiseen liittyvät asiat ovat riippumattomia GeoGebran käyttötavasta, eli toimivat muulloinkin kuin material_id
-attribuutin kanssa.
6. ggb-tiedoston käyttäminen
Mikäli jossakin verkossa on tehtävää varten tehty ggb
-tiedosto, voidaan myös sitä käyttää suoraan:
``` {plugin="csPlugin" #geo8}
type: geogebra
borders: false
norun: true
width: 840
height: 500
filename: "https://dev.geogebra.org/examples/ggb/sine-curves.ggb"
```
Edellä on jouduttu säätämään leveyttä ja korkeutta jotta alkuperäisen tehtävän kaikki ominaisuudet näkyisivät.
Tähän liittyy samat plussat ja miinukset kuin GorGebran tunnisteen käyttöönkin.
7. Base64 koodatun ggb-datan käyttö
Jos jostakin saa tehtävän base64-koodattuna ggb-tiedostona, voidaan sitä käyttää suoraan. Tämä dokumentin lopussa oleva työkalu on yksi tapa tuottaa base64-koodattuja ggb-tiedostoja.
Base64 koodaus on sellainen, joka muuttaa binäärisen datan (jossa kunkin yksittäisen tavun arvo voi olla mikä tahansa välillä 0-255) niin, että kaikki arvot tavallisia ASCII merkkejä (A-Z,a-z,0-9,+,/) ja niitä voilla 64 erilaista. Merkit on valittu niin, että ne ovat samat lähes kaikissa merkistöissä.
Näin tällainen tieto voidaan kuljettaa esimerkiksi leikepöydän kautta, sillä ilman koodausta rivinvaihtojen yms kohdille sattuvat erikoisemerkkejä vastaavat tavut sotkisivat datan.
GeoGebran ggb-tiedoston on zip-tiedosto, jossa on tehtävän tiedot suurimmaksi osaksi muutamana XML-tiedostona. Silloin ggb on "pahasti" binääristä dataa ja sitä ei voida kuljettaa leikepöydällä. Base64-koodattuna data voidaan kuitenkin siirtää helposti paikasta toiseen tallentamatta sitä välillä esimerkiksi tiedostoihin.
Edellisiin tässä on se ero, että annetaan -data
attribuutti ja sen perään ggbBase
64 sisältö. Miinusmerkki data
-attribuutin edessä tarkoittaa sitä, että sisältöä ei anneta erikseen selaimelle, vaan se toimitetaan ainoastaan GeoGebran käyttöön.
``` {plugin="csPlugin" #geo363}
type: geogebra
borders: false
norun: true
width: 600
height: 450
-data: UEsDBBQACAgIAGdouU4AA...BLBQYAAAAABAAEAAgBAADDEAAAAAA=
```
Rivin -data:
saa kirjoittaa myös TIMin monirivistä YAML-merkintää käyttäen:
-data: |!!
UEsDBBQACAgIA...
!!
jolloin on helpompi vaihtaa datan tilalle XML-tiedosto, jos sen katsoo paremmaksi vaihtoehdoksi.
Dataa ggb-muotoa varten saa esim olemassa olevasta GeoGebra tiedostosta niin, että sen lyhytnimen pudottaa dokumentin lopussa olevaan työkaluun kohtaan Set constraction
ja sitten load
. Sen jälkeen painaa Get contraction GGB
.
Plussia:
- kohtuullisen helppo käyttää
- koko tehtävä on tuossa yhdessä merkkijonossa ja sen voi siirtää johonkin GeoGebra-työkaluun, muokata ja palauttaa takaisin. Eli kaikki jotka TIMissä pääsevät muokkaamaan dokumenttia, voivat halutessaan muokata tehtävää.
Miinuksia:
- merkkijono on saatava kopioitua kokonaisena, muuten se ei toimi
- merkkijonoa ei voi itse käsin muutella, muokkaus pitää tehdä jollakin työkalulla
8. XML-datan käyttö
Voit saada tehtävän kuvauksen myös jostakin XML-datana. Yksi tapa saada XML-dataa on ohjeen lopussa oleva työkalu. Itse asiassa ggb
-tiedosto on zip-tiedosto jonka sisällä on muutamia XML-tiedostoja joista suurin on se, joka kelpaa tähän.
XML-dataa käytetään seuraavasti (koska XML-data on iso, on ensin vain leikattu esimerkki ja sitten seuraavasta voi avata kokonaisen esimerkin):
``` {plugin="csPlugin" #geo10}
type: geogebra
borders: false
norun: true
width: 600
height: 450
-data: |!!
<?xml version="1.0" encoding="utf-8"?>
<geogebra format="5.0" version="5.0.541.0" app="graphing" platform="w" id="29203A00-A088-4FC8-9A90-7B0F2BDD4D7A" xsi:noNamespaceSchemaLocation="http://www.geogebra.org/ggb.xsd" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<gui>
<window width="1198" height="600" />
... ISO pala poistettu välistä ...
<element type="conicpart" label="d">
<show object="true" label="false"/>
<objColor r="153" g="51" b="0" alpha="0.10000000149011612"/>
<layer val="0"/>
<labelMode val="0"/>
<lineStyle thickness="5" type="0" typeHidden="1" opacity="178"/>
<eigenvectors x0="1" y0="0" z0="1.0" x1="0" y1="1" z1="1.0"/>
<matrix A0="1" A1="1" A2="25.7513" A3="0" A4="5.8" A5="2.55"/>
<eqnStyle style="implicit"/>
<outlyingIntersections val="false"/>
<keepTypeOnTransform val="true"/>
</element>
</construction>
</geogebra>
!!
```
``` {plugin="csPlugin" #geo10}
type: geogebra
borders: false
norun: true
width: 600
height: 450
-data: |!!
<?xml version="1.0" encoding="utf-8"?>
<geogebra format="5.0" version="5.0.541.0" app="graphing" platform="w" id="29203A00-A088-4FC8-9A90-7B0F2BDD4D7A" xsi:noNamespaceSchemaLocation="http://www.geogebra.org/ggb.xsd" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<gui>
<window width="1198" height="600" />
<perspectives>
<perspective id="tmp">
<panes>
<pane location="" divider="0.2612687813021703" orientation="1" />
</panes>
<views>
<view id="4097" visible="false" inframe="false" stylebar="true" location="1,1,1,1" size="400" window="100,100,700,550" />
<view id="512" toolbar="0 | 1 501 5 19 , 67 | 2 15 45 18 , 7 37 | 514 3 9 , 13 44 , 47 | 16 51 | 551 550 11 , 20 22 21 23 , 55 56 57 , 12 | 69 | 510 511 , 512 513 | 533 531 , 534 532 , 522 523 , 537 536 , 535 | 521 520 | 36 , 38 49 560 | 571 30 29 570 31 33 | 17 | 540 40 41 42 , 27 28 35 , 6 , 502" visible="false" inframe="false" stylebar="false" location="1,1,1" size="500" window="100,100,600,400" />
<view id="4" toolbar="0 || 2020 , 2021 , 2022 || 2001 , 2003 , 2002 , 2004 , 2005 || 2040 , 2041 , 2042 , 2044 , 2043" visible="false" inframe="false" stylebar="false" location="1,1" size="300" window="100,100,600,400" />
<view id="8" toolbar="1001 | 1002 | 1003 || 1005 | 1004 || 1006 | 1007 | 1010 || 1008 | 1009 || 6" visible="false" inframe="false" stylebar="false" location="1,3" size="300" window="100,100,600,400" />
<view id="1" visible="true" inframe="false" stylebar="false" location="1" size="885" window="100,100,600,400" />
<view id="2" visible="true" inframe="false" stylebar="false" location="3" size="313" window="100,100,600,400" />
<view id="16" visible="false" inframe="false" stylebar="false" location="1" size="300" window="50,50,500,500" />
<view id="32" visible="false" inframe="false" stylebar="true" location="1" size="300" window="50,50,500,500" />
<view id="64" toolbar="0" visible="false" inframe="false" stylebar="false" location="1" size="480" window="50,50,500,500" />
<view id="128" visible="false" inframe="false" stylebar="false" location="1" size="480" window="50,50,500,500" />
<view id="70" toolbar="0 || 2020 || 2021 || 2022" visible="false" inframe="false" stylebar="true" location="1" size="900" window="50,50,500,500" />
<view id="43" visible="false" inframe="false" stylebar="false" location="1" size="450" window="50,50,500,500" />
</views>
<toolbar show="true" items="0 77 73 62 | 1 501 67 , 5 19 , 72 75 76 | 2 15 45 , 18 65 , 7 37 | 4 3 8 9 , 13 44 , 58 , 47 | 16 51 64 , 70 | 10 34 53 11 , 24 20 22 , 21 23 | 55 56 57 , 12 | 36 46 , 38 49 50 , 71 14 68 | 30 29 54 32 31 33 | 25 17 26 60 52 61 | 40 41 42 , 27 28 35 , 6" position="1" help="false" />
<input show="true" cmd="true" top="algebra" />
<dockBar show="false" east="false" />
</perspective>
</perspectives>
<labelingStyle val="3"/>
<font size="16"/>
</gui>
<euclidianView>
<viewNumber viewNo="1"/>
<size width="884" height="597"/>
<coordSystem xZero="491.50000000000006" yZero="84.5" scale="49.99999999999998" yscale="49.99999999999998"/>
<evSettings axes="false" grid="false" gridIsBold="false" pointCapturing="3" rightAngleStyle="1" checkboxSize="26" gridType="3"/>
<bgColor r="255" g="255" b="255"/>
<axesColor r="0" g="0" b="0"/>
<gridColor r="192" g="192" b="192"/>
<lineStyle axes="1" grid="0"/>
<axis id="0" show="false" label="" unitLabel="" tickStyle="1" showNumbers="true"/>
<axis id="1" show="false" label="" unitLabel="" tickStyle="1" showNumbers="true"/>
</euclidianView>
<algebraView>
<mode val="1"/>
<collapsed val="3"/>
</algebraView>
<kernel>
<continuous val="false"/>
<usePathAndRegionParameters val="true"/>
<decimals val="2"/>
<angleUnit val="degree"/>
<algebraStyle val="3" spreadsheet="0"/>
<coordStyle val="0"/>
</kernel>
<tableview min="-2" max="2" step="1"/>
<scripting blocked="false" disabled="false"/>
<construction title="" author="" date="">
<element type="point" label="A">
<show object="true" label="true"/>
<objColor r="77" g="77" b="255" alpha="0"/>
<layer val="0"/>
<labelOffset x="-32" y="0"/>
<labelMode val="0"/>
<animation step="1" speed="1" type="1" playing="false"/>
<coords x="-5.8" y="-2.55" z="1"/>
<pointSize val="5"/>
<pointStyle val="0"/>
</element>
<element type="point" label="B">
<show object="true" label="true"/>
<objColor r="77" g="77" b="255" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<animation step="1" speed="1" type="1" playing="false"/>
<coords x="-2.54" y="-0.61" z="1"/>
<pointSize val="5"/>
<pointStyle val="0"/>
</element>
<command name="Circle">
<input a0="A" a1="B"/>
<output a0="c"/>
</command>
<element type="conic" label="c">
<show object="true" label="false"/>
<objColor r="0" g="0" b="0" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<lineStyle thickness="5" type="0" typeHidden="1" opacity="178"/>
<eigenvectors x0="1" y0="0" z0="1.0" x1="0" y1="1" z1="1.0"/>
<matrix A0="1" A1="1" A2="25.7513" A3="0" A4="5.8" A5="2.55"/>
<eqnStyle style="specific"/>
</element>
<command name="Rotate">
<input a0="B" a1="60°" a2="A"/>
<output a0="B'"/>
</command>
<element type="point" label="B'">
<show object="true" label="true"/>
<objColor r="77" g="77" b="255" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<coords x="-5.85008928334181" y="1.2432428163372702" z="1"/>
<pointSize val="5"/>
<pointStyle val="0"/>
</element>
<command name="Angle">
<input a0="B" a1="A" a2="B'"/>
<output a0="α"/>
</command>
<element type="angle" label="α">
<angleStyle val="0"/>
<value val="1.0471975511965974"/>
<show object="true" label="true"/>
<objColor r="0" g="100" b="0" alpha="0.10000000149011612"/>
<layer val="0"/>
<labelOffset x="19" y="16"/>
<labelMode val="1"/>
<lineStyle thickness="5" type="0" typeHidden="2" opacity="178"/>
<arcSize val="30"/>
</element>
<command name="CircleSector">
<input a0="A" a1="B" a2="B'"/>
<output a0="d"/>
</command>
<element type="conicpart" label="d">
<show object="true" label="false"/>
<objColor r="153" g="51" b="0" alpha="0.10000000149011612"/>
<layer val="0"/>
<labelMode val="0"/>
<lineStyle thickness="5" type="0" typeHidden="1" opacity="178"/>
<eigenvectors x0="1" y0="0" z0="1.0" x1="0" y1="1" z1="1.0"/>
<matrix A0="1" A1="1" A2="25.7513" A3="0" A4="5.8" A5="2.55"/>
<eqnStyle style="implicit"/>
<outlyingIntersections val="false"/>
<keepTypeOnTransform val="true"/>
</element>
</construction>
</geogebra>
!!
```
Edellä mainitulla työkalulla saa myös XML-muodon.
Plussia:
- kohtuullisen helppo käyttää
- koko tehtävä on tuossa yhdessä merkkijonossa ja sen voi siirtää johonkin GeoGebra-työkaluun, muokata ja palauttaa takaisin. Eli kaikki jotka TIMissä pääsevät muokkaamaan dokumenttia, voivat halutessaan muokata tehtävää.
- jos ymmärtää rakenteen, voi pikkumuutokset tehdä suoraan XML-dataan
Miinuksia:
- merkkijono on saatava kopioitua kokonaisena, muuten se ei toimi
9. Komentojen käyttö
Tietyssä mielessä paras tapa säilyttää tehtävät olisi käyttää komentoja. Komentoja voi esimerkiksi kopioda tämän dokumentin lopussa olevasta työkalusta ja sitten muokata tarpeen mukaan. Toistaiseksi komentojen kaveriksi tarvii vähintään minimaalisen XML:än, jolla alustetaan näkymä halutuksi. Tuota XML:ää voi joutua muuttamaan kuvion keskityksen ja zoomauksen takia.
Pohjaksi voi toki ottaa minkä tahansa material_id
, ggb-tieodston, ggbBase64- tai XML-datan pohjalta tehdyn version. Itse asiassa voikin olla hyvä idea että on jokin vakiopohja tietyille tehtävätyypeille (esim material-id
:n pohjalta) ja sitten tehtäviä tehdään tämän päälle "vain" ilmoittalla kommennot jotka tulee lisäksi.
``` {plugin="csPlugin" #geoc1}
type: geogebra
borders: false
norun: true
width: 600
height: 450
javascript: |!!
!!
commands: |!!
A = (0, 0)
B = (3, 0)
c: Circle[A, B]
B': Rotate[B, 60°, A]
α: Angle[B, A, B']
d: CircleSector[A, B, B']
!!
-data: |!!
<geogebra format="5.0">
<euclidianView>
<coordSystem xZero="250" yZero="200" scale="50" yscale="50"/>
<axis id="0" show="false" />
<axis id="1" show="false" />
</euclidianView>
</geogebra>
!!
```
Plussat:
- täysi omistusoikeus tehtävään ja kuka tahansa TIM-käyttäjä jolla on dokumentin muokkausoikeus, voi muokata tehtävää
- vie TIMistä vähemmän tilaa kuin ggb tai XML-versio.
- pisteytyksen tekeminen helpointa, kun on tarkka kontrolli olioiden nimiin
Miinukset:
työläämpi tehdä kuin muut versiot
esim labelit tulevat automaattisesti näkyviin ja niitä pitää erikseen piilotella lisäämällä käsin komentoja tyyliin:
ShowLabel(B, false)
9.1 Kikkoja
Pienenä ongelmana komentojen käytössä on se, että oletuksena kaikki labelit tulevat näkyviin ja mm sidot pisteet voivat mennä "hassuihin" paikkoihin.
Otetaan esimerkiksi alkuperäinen tehtävä material_id
:n mukaan pwnfhg4d
:
Kun tämä id laitetaan lopussa olevaan työkaluun ja pyydetään sieltä vastaavat komennot, saadaan komennot:
A: (0, 0)
c: Circle[A, 1]
B: Point[c]
B': Rotate[B, 180°, A]
f: Segment[B, B']
α: Angle[B', A, B]
d: CircleArc[A, B, B']
C: Point[d]
g: Segment[C, B]
h: Segment[B', C]
β: Angle[B', C, B]
ja kun nämä komennot kopioidaan komentopohjaan, saadaan tulos:
Ensinnäkin kuva jää pieneksi, koska edellisestä komentojen mallista kopioidussa pohjassa on pienempi skaalaus. Siksi muutetaan skaalausta:
<euclidianView>
<coordSystem xZero="250" yZero="200" scale="187" yscale="187"/>
Tarkan skaalauksen näkee työkalulla, kun ottaa XML-datan ja katsoo sen vastaavan rivin. Samalla voitaisiin muuttaa myös keskitystä vastaavasti, mutta tämä on melkein parempi nyt. Toinen oleellinen vika on että pisteet ovat eri järjestyksessä, kuviot eri värisiä ja erityisesti piste C on pisteen B päällä.
Ongelmat saadaan korjattua kun komentoihin lisätään:
ShowLabel(B, false)
ShowLabel(B',false)
ShowLabel(A,false)
ShowLabel(C,false)
ShowLabel(β,false)
SetLabelMode(α,2)
SetCoords(B,-1,1)
SetCoords(C,-2,-1)
SetColor(A,"Black")
SetColor(C,"Orange")
SetColor(α,"Magenta")
SetColor(β,"Green")
Näistä yksi tärkeimistä komennoista on
SetCoords(B,-1,1)
jolla saadaan alkuperäinen piste B
kiertymään lähimmäksi paikkaa -1,1
. Sitten C
, joka on alunperin B
:n päällä, saadaan siirrettyä kauemmaksi B
:stä komennolla:
SetCoords(C,-2,-1)
Loput komennot ovatkin "vain" ulkoasun viilaamista.
Esimerkiksi labelin näyttömuodon muuttaminen komennolla SetLabelMode(α,2)
.
10. JavaScriptin käyttö
Samat asiat voi tehdä myös JavaScriptillä. Lue lisää GeoGebran JavaScriptAPI:sta:
Periaatteessa koko tehtävä voidaan tehdä suoraan GeoGebran JavaScriptAPI:n ohjeilla kun sisältö kirjoitetaan srchtml
-attribuutin alle. Jos kuitenkin halutaan alustaa tehtävää ja/tai käyttää opiskelijan tallenusta tai pistelaskua, pitää tietyt funktiot olla toteutettuna:
function getData()
- palauttaa GeoGebra-tehtävän tilan halutulla tavalla, mahdollisesti myös pisteet.function setData(geostate)
- asettaa GeoGebra-tehtävän aiemmin palautettuun tilaan.
Mikäli EI kirjoiteta attribuuttia srchtml
on molemmat funktiot valmiiksi toteutettuna ja ne ovat:
function getData(){ if ( P.getData ) return P.getData(); }
function setData(geostate) { if ( P.setData ) P.setData(geostate); }
Tarkoitus on että tehtävän laatija voi itse muokata silloin noita funktioita:
P.getData()
P.setData(geostate)
Oletuksena funktio P.getData()
on:
P.getData = function(){
return {"data": ggbApplet.getBase64()};
}
Eli tehtävän tilaksi palautetaan koko tehtävän ggbBase64-data. Moniin tarkoituksiin tämä on turhan iso, koska usein tehtävissä liikutetaan vain muutamaa pistettä. Siksi tämä kannattaa usein kirjoittaa uusiksi. Silloin vastaavasti pitää korvata myös funktio:
P.setData = function(geostate) {
P.setDataInit(ggbApplet, geostate);
}
Tätä funktiota kutsutaan aina kun selataan tehtävien vastauksia ja vaihdetaan tehtävän tekijää tai tehtävän vastauskertaa. Funktiota:
P.setDataInit(ggbApplet, geostate);
kannattaa kutsua tästä ja sitä kutsutaan automaattisesti myös heti tehtävän latauksen jälkeen. Eli usein käytännössä nimenomaan tämä funktio kirjoitetaan uusiksi. Sen oletustoteutus on:
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
}
Teemme nyt aluksi malliksi äskeisestä ympyrä-tehtävästä samanlaisen version, mutta niin, että lisäkomennot peruskomentojen jälkeen tehdään JavaScriptillä.
``` {plugin="csPlugin" #geoj1}
type: geogebra
borders: false
norun: true
width: 600
height: 450
commands: |!!
A: (0, 0)
c: Circle[A, 1]
B: Point[c]
B': Rotate[B, 180°, A]
f: Segment[B, B']
α: Angle[B', A, B]
d: CircleArc[A, B, B']
C: Point[d]
g: Segment[C, B]
h: Segment[B', C]
β: Angle[B', C, B]
SetColor(A,"Black")
SetColor(C,"Orange")
SetColor(α,"Magenta")
SetColor(β,"Green")
!!
javascript: |!!
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
timgeo.setAllLabelsVisible(api, false); // kaikki labelit piiloon
timgeo.setLabelStyle(api,"α",2); // näytetään asteluku ja näkyviin
api.setCoords('B',-1,1); // etsitään lähin kehän piste B:lle
api.setCoords('C',-2,-1);
}
!!
-data: |!!
<geogebra format="5.0">
<euclidianView>
<coordSystem xZero="250" yZero="200" scale="187" yscale="187"/>
<axis id="0" show="false" />
<axis id="1" show="false" />
</euclidianView>
</geogebra>
!!
```
Värit voitaisiin asettaa
api.setColor("B", 21,101,192);
kutsuilla, mutta sitten pitää itse miettiä värien koodit. Tosin värikoodit voi katsoa työkalussa kun ottaa olio XML-koodin ja sieltä voi katsoa kyseisen olion värikoodit rivistä:
<objColor r="21" g="101" b="192" alpha="0"/>
JavaScriptillä voidaan myös ajaa komentoja tyyliin:
api.evalCommand(
'SetColor(A,"Black")\n'+
'SetColor(C,"Orange")\n'+
'SetColor(α,"Magenta")\n'+
'SetColor(β,"Green")\n'
);
mutta koska tämä on pidempi kuin suora komentojen antaminen, voi olla järkevämpää asettaa värit suoraan komento-listassa.
11. Näkymän säätäminen parametreilla
Alustavaa näkymää voidaan säätää GeoGebran appletin parametreilla. Niistä voit lukea lisää:
Alla esimerkkikoodi. Tehtävästä tulisi tyhjä, jos jätettäsiin commands
osa tyhjäksi.
``` {plugin="csPlugin" #geop1}
type: geogebra
borders: false
norun: true
width: 800
height: 600
commands: |!!
A = (0, 0)
B = (3, 0)
c: Circle[A, B]
B': Rotate[B, 60°, A]
α: Angle[B, A, B']
d: CircleSector[A, B, B']
!!
javascript: |!!
P.appName = "graphing";
P.height = 600;
P.showMenuBar = true;
P.showAlgebraInput = true;
P.showToolBar = true;
P.customToolBar = "0 77 73 62 | 1 501 67 , 5 19 , 72 75 76 | 2 15 45 , 18 65 , 7 37 | 4 3 8 9 , 13 44 , 58 , 47 | 16 51 64 , 70 | 10 34 53 11 , 24 20 22 , 21 23 | 55 56 57 , 12 | 36 46 , 38 49 50 , 71 14 68 | 30 29 54 32 31 33 | 25 17 26 60 52 61 | 40 41 42 , 27 28 35 , 6";
P.showToolBarHelp = true;
P.showResetIcon = true;
P.enableLabelDrags = true;
P.enableShiftDragZoom = true;
P.showZoomButtons = true;
P.capturingThreshold = 3;
P.showFullscreenButton = true;
!!
-data: |!!
<geogebra format="5.0">
<euclidianView>
<coordSystem xZero="250" yZero="200" scale="50" yscale="50"/>
<axis id="0" show="false" />
<axis id="1" show="false" />
</euclidianView>
</geogebra>
!!
```
Jos edellä on
P.appName = "classic";
niin, saadaan "perinteisen" näköinen GeoGebra-tehtävä.
12. GeoGebran sovellustyypit (app)
GeoGebrassa on useita eri sovellustyyppejä (app):
- Scientific, Graphing (oletus), Geometry, 3D, CAS, Classic
- Comparison of GeoGebra Math Apps
Tarvittaessa app-tyyppiä voidaan vaihtaa esim 3D:ksi
``` {plugin="csPlugin" #geo2}
type: geogebra
borders: false
norun: true
width: 1000
height: 800
javascript: |!!
P.appName = "3D";
!!
-data: |!!
UEs...AIAQAAaxIAAAAA
!!
```
13. Muita asetuksia
Jostakin syystä esimerkiksi jos halutaan yhtäaikaa näyttää sekä 3D että 2D säätimiä, pitää laittaa
``` {plugin="csPlugin" #geo2}
type: geogebra
...
javascript: |!!
P.showAlgebraInput = true;
!!
...
```
13.1 Mahdolliset asetukset:
P.appName = "graphing";
P.width = 1200;
P.height = 600;
P.showMenuBar = true;
P.showAlgebraInput = true;
P.showToolBar = true;
P.customToolBar = "0 77 73 62 | 1 501 67 , 5 19 , 72 75 76 | 2 15 45 , 18 65 , 7 37 | 4 3 8 9 , 13 44 , 58 , 47 | 16 51 64 , 70 | 10 34 53 11 , 24 20 22 , 21 23 | 55 56 57 , 12 | 36 46 , 38 49 50 , 71 14 68 | 30 29 54 32 31 33 | 25 17 26 60 52 61 | 40 41 42 , 27 28 35 , 6";
P.showToolBarHelp = true;
P.showResetIcon = true;
P.enableLabelDrags = true;
P.enableShiftDragZoom = true;
P.enableRightClick = false;
P.errorDialogsActive = false;
P.useBrowserForJS = false;
P.allowStyleBar = false;
P.preventFocus = true;
P.showZoomButtons = true;
P.capturingThreshold = 3;
14. Käyttäjän vastauksen tallentaminen
Kaikki edellä kuvatut tavat voidaan muuttaa sellaiseksi, että käyttäjä voi tallentaan tilanteen. Tähän riittää poistaa rivi:
norun: true
tai vaihtaa se
norun: false
Otetaan esimerkiksi tehtävä, jossa on piste ympyrän kehältä:
``` {plugin="csPlugin" #geoyt1}
type: geogebra
borders: false
norun: true
width: 650
height: 500
material_id: "pwnfhg4d"
```
Tässä käyttäjä voi oikeastaan liikuttaa vaan pisteitä A
, B
ja C
(vihreä, sininen ja oranssi). Tällöin tehtävän koko tilan tallentaminen on melkoista muistitilan haaskausta.
14.1 Esimerkki kolmen pisteen tilasta
Jotta koko tilaa ei turhaan tallenneta, kirjoitetaan uudelleen JavaScript osuus, joka kertoo mitä tallennetaan ja miten tallennus otetaan takaisin:
``` {plugin="csPlugin" #geoyt2}
type: geogebra
width: 650
height: 500
material_id: "pwnfhg4d"
javascript: |!!
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
timgeo.setPointsCoords(api, geostate.usercode);
}
P.getData = function(){
return {"usercode": timgeo.getObjValue(ggbApplet,"A,B,C")};
}
!!
```
Tässä on raamit palautettu takaisin, jotta käyttäjä mieltää paremmin, että tehtävään kuuluu Tallenna-painike. Ja painike siis tuli näkyviin kun norun
jätettiin pois.
Kokeile liikutella oranssia pistettä (C
) ja sen yläpuolella olevaa sinistä pistettä (B
) ja paina aina välillä Tallenna-painiketta. Sitten voit selailla tallentamiasi vastauksia tehtävän yläpuolella olevalla valitsimella. Voi vaihtaa sivun yläreunasta Velp-näkymään ja sitten ruksia tehtävän päällä olevan Velp
-ruksin. Nyt tehtävää selatessa näet mitä dataa on tallentunut kullakin kerralla.
14.2 Tilan tallentaminen
Tallentaminen perustuu siihen, että kun painetaan Tallenna-painiketta, TIM kutsuu funktiota P.getData()
. Kirjoitimme tähän funktioon tässä esimerkissä:
P.getData = function(){
return {"usercode": timgeo.getObjValue(ggbApplet,"A,B,C")};
}
Tämä tarkoittaa että tehtävän tilana palautetaan JSON-olio, jossa on "ominaisuus" (attribuutti) usercode
.
Huomaa että koska api
ei ole funktion parametrina, pitää käyttää globaalia muuttujaa ggbApplet
ilmaisemaan mitä GeoGebra-tehtävää käsitellään.
Attribuuttien nimet saa valita melko vapaasti, ainoastaan muutama:
data
- varattu koko tilan talletamiseksi joko ggbBase64- tai XML-muodossausercode
- varattu siihen käyttöön, että tämä tieto näytettään VELP-muotoisessa selailussa ja tähän tallennettua tekstiä voidaan pisteyttää TIMin normaaleilla pisteytystavoilla. Samoin tämä arvo tulostuu raportteihin.
Tehtävän tilaa voi tallentaa useampaankin attribuuttiin. Esimerkiksi edellä voisi olla
P.getData = function(){
return {
"usercode": timgeo.getObjValue(ggbApplet,"C"),
"userstate": timgeo.getObjValue(ggbApplet,"A,B,C")
};
}
Tämä tarkoittaisi sitä, että "näkyvästi" on tallennettu vain pisteen C
arvo, mutta sisäisesti kaikkien liikuteltavien pisteiden arvo. Kun tieto otetaan takaisin käyttöön, pitäisi siihen käyttää nyt userstate
-attribuutin arvoa.
Vastaavasti jos koko tila olisi "pakko" tallentaa XML:änä ja sitten haluttaisiin näyttää VELP-selailussa ja raporteissa vain C-pisteen kooordinaattia, niin tilana voitaisiin palauttaa:
P.getData = function(){
return {
"usercode": timgeo.getObjValue(ggbApplet,"C"),
"data": ggbApplet.getBase64()
};
}
Tällöin valmiiksi tehty tilanpalautus osaa näyttää uuden tilan.
Lista kaikista käytössä olevista GeoGebran JavaScriptAPIN:n funktioista löytyy:
14.3 TIMin apufunktiot GeoGebran tietojen käsittelyyn
Näiden lisäksi on tukku TIMin `timgeo'-olioon kirjoitettuja apufunktioita, joista suurinta osaa voi testata dokumentin lopun työkalulla.
getConstructionState(api)
- palauttaa tehtävän koko tilan merkkijonona. Tätä ei sellaisenaan juurikaan voi käyttää hyödyksi, mutta siitä voi opiskelella mitä kannattaisi tallentaa
getObjXML(api, objnames)
- palauttaa yhden tain usean olion tilan XML:nä. Tätä voi joskus käyttää tilan tallentamiseen, koska täällä on myös värit yms mukana.
getObjValue(api, objnames)
- palauttaa olion tai olioiden arvon. Arvo voi olla järkevää tallentaa tilana kuten esimerkissä.
getObjsCommands(api, objnames)
- palauttaa olion tai olioiden kommennot
getObjCommand(api, name)
- kuten edellä, mutta vai yhdestä olioista. Käytännössä tätä ei tarvitse kun voi aina kutsua tuota monikkomuotoista yhdellä olioilla.
getCommands(api)
- palauttaa kaikki kommenot. Värit yms jäävät puuttumaan.
setState(api, geostate)
- asettaa tehtävän tilan
geostate
-olion tietojen mukaan. Käyttäädata
jacommands
-attribuutteja.
setLabelsVisible(api, objnames, visible)
- asettaa valittujen labeleiden arvot näkyviin
true
tai poisfalse
setAllLabelsVisible(api, visible)
- asettaa tehtävän kaikki labelit näkyviin tai pois
setLabelStyle(api, objnames, style)
- asettaa valituille labeleille halutun tyylin. Jos piilotettuja näyttää ne samalla.
setPointsCoords(api, lines)
- asettaa merkkijonon perusteella olioiden koordinaatit otaten huomioon, että sidotut pisteet laitetaan lähimmäksi pyydettyä pistettä ja sidontaa ei menetetä. Käytetään yhdessä
getObjValue
funkion kanssa.
setXmlProperty(api, obj, prop)
- asettaan olio ominaisuuden XML attribuutti-rivin perusteella
setTextValue(api, name, value)
- asettaa tesktiolion tekstiarvon. Jos value on
undifined
ei tee mitään
getPureValue(api, objnames)
- palauttaa olioiden arvot ilman mitään ylimääräisiä merkkejä. jos esim
getObjValue
palauttaisi60°
, niin tämä palauttaa '60'.
getNumberValue(api, objnames)
- palauttaa olioiden numeeriset arvot, kulmista radiaaneina
deleteObject(api, objnames)
- tuhoaa nimetyt oliot
deleteAllObjects(api)
- tuhoaa kaikki oliot
removeLines(s, remove)
- poistaa merkkijonosta kaikki rivit joissa esiintyy termi remove (voi olla regexp). Käytetään esim poistamaan komentojoukosta sellaiset kommennot, joita on tuotettu yhdellä komennolla useita, kuten esim
InteriorAngles
. Näin tilaa palautettaessa ei komennot moninkertaistu. Poistetut komennot pitää yleensä lisätä sitten yhtenä kappaleena loppuun. Jos tätä joutuu paljon käyttämään, kannattaa harkita kannattaisiko tila silloin kuitenkin tallentaa ggbBase64 muodossa (joka ostaa oletuksen lukea).
14.4 Raportti näyttää usercoden
Jos em. tehtävästä otetaan raportti opettajan näkymässä painalla tehtävän vieressä All answers
-linkkiä, saadaan esimerkiksi:
Ankka Aku; akankka; 503.geoj1; 2019-06-01 14:52:16.213731+00:00; 5;
A = (0.0, 0.0)
B = (-0.71, 0.71)
C = (0.64, -0.76)
----------------------------------------------------------------------------------
Lappalainen Vesa; vesal; 503.geoj1; 2019-06-01 16:08:38.980675+00:00; 5;
A = (0.24, 0.01)
B = (0.26, 1.01)
C = (-0.2, -0.89)
14.5 Tilan palauttaminen selattaessa
Kun käyttäjä avaa sivun uudelleen ja tehtävä ladataan, kutsutaan funktiota:
P.setDataInit
Vastaavasti jos vastausselaimella selataan vastauksia, niin vastauksen tai opettajan tilassa myös tekijän vaihtuessa kutsutaan funktiota
P.getData
Oletuksena tästä funktiosta kutsutaan tuota samaa P.setDataInit
funktiota:
P.setData = function(geostate) {
P.setDataInit(ggbApplet, geostate);
}
Tätä tarvitsee muuttaa lähinnä silloin, jos tehtävä on luonteeltaan sellainen, että käyttäjän toimenpiteet luovat uusia olioita (esim pisteitä) ja ne pitää hävittää ensin näytöstä. Silloin ennen setDataInit
-kutsua yleensä tyhjennetään tehtäväalue ja sitten luodaan uudelleen. Tyhjäntämien voi olla tilanteesta riippuen joku komennoista:
ggbApplet.reset();
ggbApplet.newConstruction();
timgeo.deleteAllObjects();
Yksinkertaisissa tapauksissa funktiossa setDataInit
pitäisi tallennettu tieto palauttaa näyttöön. Jos esimerkiksi on tallennettu pisteiden arvoja, niin ne voidaan palauttaa sen mukaan. GeoGebran valmiissa Apissa on funktio
void setCoords(String objName, double x, double y)
joka sopisi käyttöön, mutta
timgeo.getObjValue(ggbApplet,"A,B,C")
on palauttanut merkkijonon joka on muotoa:
A = (0, 0)
B = (-0.74, 0.68)
C = (-0.9, -0.43)
Tämän käsittelyn helpottamiseksi on siis kutsu:
timgeo.setPointsCoords(api, geostate.usercode);
jolla pisteiden arvot laitetaan kohdalleen. Tämä käyttäminen on sikäli järkevä, että jos on sidottuja pisteitä esimerkiksi ympyrän kehällä, niin pistettä ei irroteta kehältä, vaan etsitään lähin piste niin että sidonta säilyy.
15. Pisteiden antaminen
Yksi suurimmasta TIMin oman GeoGebra-komponentin eduista on se, että sillä voidaan myös pisteyttää opiskelijoiden vastauksia.
Tehtävän pisteyttäminen voi perustua pisteiden laskemiseen GeoGebran koodin puolella tai pisteden laskemiseen TIMissä normaaleilla TIMin tavoilla.
GeoGebran puolella pisteyttäminen on sikäli järkevää, että data on alkuperäisessä muodossa ja voidaan käyttää GeoGebran funktioita arvojen tutkimiseen. Huonona puolena tässä on se, että taitavalla JavaScript-käyttäjälle jää mahdollisuus "huijata" ja tehdä vastaava pistemäärän lähetys itse. Eli tämän tavan käyttöä pitää harkita pääsykoe yms. luonteisissa tilanteissa, joissa pisteillä on paljon merkitystä.
Edelleen kannattaa huomata, että voidaan käyttää myös mitä tahansa muuta edellä esitettyä tapaa tehtävän ylläpitämiseksi, kuin tässä esimerkissä oleva material_id
(siis ggb-tiedosto, ggbBase64-data, XML_data, komennot, JavaScrpt tai mikä tahansa niiden yhdistelmä). Tässä esimerkkinä käyetään material_id
vain siksi, että valmis koodi pysyy lyhimpänä.
15.1 Pisteiden laskeminen GeoGebran puolella
Oletetaan että edellisessä ympyrätehtävässä olisi annettu tavoitteeksi saada piste C
niin, että kateetit ovat mahdollisimman saman mittaiset. Sovitaan että tehtävästä saa 2 pistettä jos ero on alle 5% ja 1 pistettä jos ero on alle 10%.
Pistetään tilapäisesti kaikki muuttujat näkyville (tässä voisi käyttää myös sivun lopun työkalua). Voit kokeilla tässä pisteiden saamista useita kertoa. Ehkä % olivat jopa liian tiukkoja.
Eli meitä kiinnostaa sivujen h
ja g
pituudet ja niiden suhteet.
Tarvittava koodi:
``` {plugin="csPlugin" #geoyt3}
type: geogebra
-pointsRule: # Tämä tarvitaan jotta TIM tietää mistä kentästä
pointsKey: points # pisteet löytyvät
width: 650
height: 500
stem: Liikuta pistettä C niin, että kateetit ovat mahdollisimman yhtäpitkiä
material_id: "pwnfhg4d"
javascript: |!!
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
timgeo.setAllLabelsVisible(api, true); // Jotta nähtiin mitä olioita
timgeo.setPointsCoords(api, geostate.usercode);
}
P.getData = function(){
let points = 0; // Lasketaan pisteet sovituilla säännöillä
let api = ggbApplet; // lyhennetään api:n nimi
let h = api.getValue('h'); // haetaan sivujen pituudet
let g = api.getValue('g');
let diff = Math.abs(h-g); // pituuksien erotus
let m = Math.max(h,g); // kumpiko sivu on pidempi
if ( diff < 0.10*m ) points = 1; // verrataan eroa siihen
if ( diff < 0.05*m ) points = 2;
return {
"usercode": timgeo.getObjValue(api,"A,B,C"),
"points": points, // Palautetaan myös tehtävän pistemäärä
};
}
!!
```
15.2 Viestin näyttäminen vastauksesta
Mikäli vastaukseen liittyen haluaa näyttää jonkin viestin, voi sen tehdä käyttäen pisteiden palautuksessa message
-attribuuttia:
P.getData = function(){
let points = 0;
let api = ggbApplet; // lyhennetään api:n nimi
let v = timgeo.getPureValue(ggbApplet,'v');
let message = "";
if ( Math.round(v) == v ) message = "Hienoa pyöristit! 😊";
else message = 'Voi ei, unohdit pyöristää! 😥?';
if ( v == 24 ) points = 2;
return {
"usercode": v,
"data": api.getXML(),
"points": points, // Palautetaan myös tehtävän pistemäärä
"message": message,
};
}
Viesti voi olla mitä tahansa HTML:ää ja sen voi muodostaa ihan miten monimutkaisesti tahansa käyttäen JavaScriptiä. Eli sen avulla voi yrittää johdatella vastaajaa oikeaan suuntaan.
15.3 Pisteiden laskeminen TIMin normaaleilla tavoilla
Aloitetaan esimerkillä, jossa käyttäjän pitää osata kirjoittaa kulman nimi. Koodi on tehty XML-datasta, joten se on sen verran pitkä, että se pitää aukaista alta erikseen.
``` {plugin="csPlugin" #geoa2}
type: geogebra
stem: "Kirjoita kulman nimi pisteiden nimiä käyttäen"
-pointsRule:
expectCodePlain: "DEF"
width: 600
height: 320
javascript: |!!
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
timgeo.setPointsCoords(api, geostate.userpts); // käyttäjän pisteiden paikat
api.evalCommand(geostate.usercmds); // kirjoitettu teksti takaisin
}
P.getData = function(){
return {
"usercode": ggbApplet.getValueString('kulmannimi'),
"userpts": timgeo.getObjValue(ggbApplet,"D,E,F"),
"usercmds": timgeo.getObjCommand(ggbApplet, 'kulmannimi'),
};
}
!!
commands: |!!
!!
-objxml: |!!
!!
-data: |!!
<?xml version="1.0" encoding="utf-8"?>
<geogebra format="5.0" version="5.0.541.0" app="graphing" platform="w" id="B2F82C16-907E-4E3B-ACFE-16BD2BED0CB9" xsi:noNamespaceSchemaLocation="http://www.geogebra.org/ggb.xsd" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<gui>
<window width="1200" height="600" />
<perspectives>
<perspective id="tmp">
<panes>
<pane location="" divider="0.31583333333333335" orientation="1" />
</panes>
<views>
<view id="4097" visible="false" inframe="false" stylebar="true" location="1,1,1,1" size="400" window="100,100,700,550" />
<view id="512" toolbar="0 | 1 501 5 19 , 67 | 2 15 45 18 , 7 37 | 514 3 9 , 13 44 , 47 | 16 51 | 551 550 11 , 20 22 21 23 , 55 56 57 , 12 | 69 | 510 511 , 512 513 | 533 531 , 534 532 , 522 523 , 537 536 , 535 | 521 520 | 36 , 38 49 560 | 571 30 29 570 31 33 | 17 | 540 40 41 42 , 27 28 35 , 6 , 502" visible="false" inframe="false" stylebar="false" location="1,1,1" size="500" window="100,100,600,400" />
<view id="4" toolbar="0 || 2020 , 2021 , 2022 || 2001 , 2003 , 2002 , 2004 , 2005 || 2040 , 2041 , 2042 , 2044 , 2043" visible="false" inframe="false" stylebar="false" location="1,1" size="300" window="100,100,600,400" />
<view id="8" toolbar="1001 | 1002 | 1003 || 1005 | 1004 || 1006 | 1007 | 1010 || 1008 | 1009 || 6" visible="false" inframe="false" stylebar="false" location="1,3" size="300" window="100,100,600,400" />
<view id="1" visible="true" inframe="false" stylebar="false" location="1" size="819" window="100,100,600,400" />
<view id="2" visible="true" inframe="false" stylebar="false" location="3" size="379" window="100,100,600,400" />
<view id="16" visible="false" inframe="false" stylebar="false" location="1" size="300" window="50,50,500,500" />
<view id="32" visible="false" inframe="false" stylebar="true" location="1" size="300" window="50,50,500,500" />
<view id="64" toolbar="0" visible="false" inframe="false" stylebar="false" location="1" size="480" window="50,50,500,500" />
<view id="128" visible="false" inframe="false" stylebar="false" location="1" size="480" window="50,50,500,500" />
<view id="70" toolbar="0 || 2020 || 2021 || 2022" visible="false" inframe="false" stylebar="true" location="1" size="900" window="50,50,500,500" />
<view id="43" visible="false" inframe="false" stylebar="false" location="1" size="450" window="50,50,500,500" />
</views>
<toolbar show="true" items="0 77 73 62 | 1 501 67 , 5 19 , 72 75 76 | 2 15 45 , 18 65 , 7 37 | 4 3 8 9 , 13 44 , 58 , 47 | 16 51 64 , 70 | 10 34 53 11 , 24 20 22 , 21 23 | 55 56 57 , 12 | 36 46 , 38 49 50 , 71 14 68 | 30 29 54 32 31 33 | 25 17 26 60 52 61 | 40 41 42 , 27 28 35 , 6" position="1" help="false" />
<input show="true" cmd="true" top="algebra" />
<dockBar show="false" east="false" />
</perspective>
</perspectives>
<labelingStyle val="1"/>
<font size="16"/>
</gui>
<euclidianView>
<viewNumber viewNo="1"/>
<size width="818" height="597"/>
<coordSystem xZero="350" yZero="130" scale="25" yscale="25"/>
<evSettings axes="false" grid="false" gridIsBold="false" pointCapturing="3" rightAngleStyle="1" checkboxSize="26" gridType="3"/>
<bgColor r="255" g="255" b="255"/>
<axesColor r="0" g="0" b="0"/>
<gridColor r="192" g="192" b="192"/>
<lineStyle axes="1" grid="0"/>
<axis id="0" show="false" label="" unitLabel="" tickStyle="0" showNumbers="false"/>
<axis id="1" show="false" label="" unitLabel="" tickStyle="0" showNumbers="false"/>
</euclidianView>
<algebraView>
<mode val="3"/>
</algebraView>
<kernel>
<continuous val="false"/>
<usePathAndRegionParameters val="true"/>
<decimals val="0"/>
<angleUnit val="degree"/>
<algebraStyle val="3" spreadsheet="0"/>
<coordStyle val="0"/>
</kernel>
<tableview min="-2" max="2" step="1"/>
<scripting blocked="false" disabled="false"/>
<construction title="" author="" date="">
<element type="point" label="D">
<show object="true" label="true"/>
<objColor r="21" g="101" b="192" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<animation step="1" speed="1" type="1" playing="false"/>
<coords x="-10" y="0" z="1"/>
<pointSize val="5"/>
<pointStyle val="0"/>
</element>
<element type="point" label="E">
<show object="true" label="true"/>
<objColor r="21" g="101" b="192" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<animation step="1" speed="1" type="1" playing="false"/>
<coords x="-0.52" y="-3.3" z="1"/>
<pointSize val="5"/>
<pointStyle val="0"/>
</element>
<command name="Segment">
<input a0="D" a1="E"/>
<output a0="h"/>
</command>
<element type="segment" label="h">
<show object="true" label="false"/>
<objColor r="0" g="0" b="0" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<coords x="3.3" y="9.48" z="33"/>
<lineStyle thickness="5" type="0" typeHidden="1" opacity="178"/>
<eqnStyle style="explicit"/>
<outlyingIntersections val="false"/>
<keepTypeOnTransform val="true"/>
</element>
<element type="point" label="F">
<show object="true" label="true"/>
<objColor r="21" g="101" b="192" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<animation step="1" speed="1" type="1" playing="false"/>
<coords x="7" y="1" z="1"/>
<pointSize val="5"/>
<pointStyle val="0"/>
</element>
<command name="Segment">
<input a0="E" a1="F"/>
<output a0="i"/>
</command>
<element type="segment" label="i">
<show object="true" label="false"/>
<objColor r="0" g="0" b="0" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<coords x="-4.3" y="7.52" z="22.58"/>
<lineStyle thickness="5" type="0" typeHidden="1" opacity="178"/>
<eqnStyle style="explicit"/>
<outlyingIntersections val="false"/>
<keepTypeOnTransform val="true"/>
</element>
<command name="Angle">
<input a0="D" a1="E" a2="F"/>
<output a0="β"/>
</command>
<element type="angle" label="β">
<angleStyle val="0"/>
<value val="3.9960074329917883"/>
<show object="true" label="true" ev="4"/>
<objColor r="0" g="0" b="255" alpha="0.1"/>
<layer val="0"/>
<labelOffset x="-10" y="27"/>
<labelMode val="1"/>
<lineStyle thickness="5" type="0" typeHidden="2" opacity="178"/>
<arcSize val="30"/>
</element>
<expression label="kulmaOkTeksti" exp="" ✔️""/>
<element type="text" label="kulmaOkTeksti">
<show object="false" label="false" ev="40"/>
<condition showObject="kulmaOk ≟ 1"/>
<objColor r="0" g="0" b="0" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<fixed val="true"/>
<startPoint x="-3" y="-5.7" z="1"/>
</element>
<expression label="kulmannimi" exp=""""/>
<element type="text" label="kulmannimi">
<show object="false" label="false" ev="40"/>
<objColor r="0" g="0" b="0" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
</element>
<command name="Textfield">
<input a0="kulmannimi"/>
<output a0="textkulma"/>
</command>
<element type="textfield" label="textkulma">
<show object="true" label="true"/>
<objColor r="0" g="0" b="0" alpha="0"/>
<layer val="0"/>
<labelOffset x="69" y="158"/>
<labelMode val="3"/>
<fixed val="true"/>
<auxiliary val="true"/>
<startPoint number="0" x="-7" y="-5" z="1"/>
<startPoint x="-7" y="-5" z="1"/> <linkedGeo exp="kulmannimi"/>
<length val="4"/>
<caption val="Kulma="/>
</element>
<command name="If">
<input a0="kulmannimi ≟ "DEF"" a1="1" a2="0"/>
<output a0="kulmaOk"/>
</command>
<element type="numeric" label="kulmaOk">
<value val="1"/>
<symbolic val="true" />
<objColor r="0" g="0" b="0" alpha="0.1"/>
</element>
</construction>
</geogebra>
!!
```
Esimerkki ei sellaisenaan ole järkevin esimerkki GeoGebran ja TIMin yhteistyöstä, koska käyttäjän täytettävä tekstilaatikko voisi olla TIMin tavallinen tekstilaatikko ja kuva voisi olla tavallinen kuva. Se että kuva on GeoGebra-kuva antaa mahdollisuuden siihen, että käyttäjä voi siirrellä pisteitä ja saada kulman "normaaliin asentoon". Ja tällöin opettajaa voisi kuvitteellisesti kiinnostaa onko oppilas käyttänyt tätä tekniikkaa. Siksi esimerkissä tallennetaan kulman nimen lisäksi se, mihin käyttäjä on pisteet siirtänyt.
Koodissa oleelliset rivit:
laitetaan TIMissä niin, että
usercode
tuottaa yhden pisteen jos tekstiksi on kirjoitettuDEF
-pointsRule: expectCodePlain: "DEF"
Lue lisää pisteytysäännöistä csPlugin-dokumentista
sitten kirjoitettaan JavaScriptiin säännöt tilan tallentamisesta ja paluttamisesta
javascript: |!! // tähän tilan käsittely !!
tilan tallentaminen:
P.getData = function(){ return { "usercode": ggbApplet.getValueString('kulmannimi'), "userpts": timgeo.getObjValue(ggbApplet,"D,E,F"), "usercmds": timgeo.getObjCommand(ggbApplet, 'kulmannimi'), }; }
Eli on haluttu, että tutkittavana asiana (
usercode
) on nimenomaan pelkkä teksti, joka on kirjoitettu kulman nimeksi. Tämä näkyy VELP selailuissa ja raporteissa. Mielenkiinnosta on tallennettu myös mihin käyttäjä on siirtänyt pisteetD
,E
jaF
vastatessaan. Eli onko hän esimerkiksi siirtänyt pisteitä niin, että saa sivunDE
oikealla jolloin kulman nimi on helppo muodostaa. Opettaja näkee sitten kunkin opiskelijan tilanteen kun selailee vastauksia. Tallennetaan myös kommenot, jota tarvitaan muuttujankulmannimi
muuttamiseksi.
tilan palauttaminen näkymään:
P.setDataInit = function (api, geostate) { timgeo.setState(api, geostate); timgeo.setPointsCoords(api, geostate.userpts); // käyttäjän pisteiden paikat api.evalCommand(geostate.usercmds); // kirjoitettu teksti takaisin }
Kun uusi käyttäjä valitaan opettajan sivulla tai opiskelija tai opettaja vaihtaa vastauksen numeroa, niin otetaan tilasta ensin perustiedot ja sitten palautetaan käyttäjän koordinaattipisteiden paikat ja lopuksi suoritetaan komennot, jotka olivat tuottaneet arvon
kulmannimi
-muuttujaan.tosin tässä tapauksessa koska
usercode
sisältää sellaisenaan ihan käypäisen arvon, voitaisiin kiroittaaevalCommand
sijaan:api.setTextValue('kulmannimi',geostate.usercode);
missä on se vika, että jos arvoa ei ole, niin se näkyy UNDEFINED. Tämän takia parempi olisi:
timgeo.setTextValue(api, 'kulmannimi', geostate.usercode);
Tällöin voitaisiin tilan tallennuksesta jättää kokonaan pois rivi, jossa komennot tallennettiin. Sen hyöty tuleekin enemmän silloin, jos tallennettavia muuttujia on enemmän. Usean muuttuujan komennot voi tallentaa esimerkiksi:
"usercmds": timgeo.getObjCommand(ggbApplet, 'kulmannimi, kulma2'),
ja palautus voidaan silti tehdä vain yhdellä lauseella kuten nytkin.
Tämän version XML-toteutuksessa on myös oikeinmerkki, joka näytetään hetki kun kentään on kirjoitettu oikea vastas ja siitä poistutaan. Ratkaisu pilaa hyödyn siitä, että tehtävä arvostellaan TIMissä ja siksi tämäkin tehtävä olisi kannattanut arvostella kokonaan GeoGebran puolella ja palauttaa TIMiin vain tila ja pisteet.
Seuraavana sama esimerkki ilman GeoGebran puolella olevaa tarkistusta ja sitten mahdollisimman pitkälle tehtynä ilman XML:ää. Tästä esimerkistä voidaan nähdä miten eri tekniikoita voidan yhdistää tehtävän tekemiseen.
``` {plugin="csPlugin" #geoa1}
type: geogebra
stem: "Kirjoita kulman nimi pisteiden nimiä käyttäen"
-pointsRule:
expectCodePlain: "DEF"
width: 600
height: 320
commands: |!!
D = (-10, 0)
E = (0, -3)
h: Segment[D, E]
F = (7, 1)
i: Segment[E, F]
β: Angle[D, E, F]
!!
javascript: |!!
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
timgeo.setAllLabelsVisible(api, false); // kaikki labelit piiloon
timgeo.setLabelsVisible(api, "D,E,F,β,textkulma", true); //muutamat takaisin
timgeo.setPointsCoords(api, geostate.userpts); // tilan palautus
api.evalCommand(geostate.usercmds);
}
P.getData = function(){
return {
"usercode": ggbApplet.getValueString('kulmannimi'),
"userpts": timgeo.getObjValue(ggbApplet,"D,E,F"),
"usercmds": timgeo.getObjCommand(ggbApplet, 'kulmannimi'),
};
}
!!
-objxml: |!!
<element type="angle" label="β">
<angleStyle val="0"/>
<show object="true" label="true" ev="4"/>
<objColor r="0" g="0" b="255" alpha="0.1"/>
<layer val="0"/>
<!-- <labelOffset x="-30" y="25"/> -->
<labelMode val="1"/>
<lineStyle thickness="5" type="0" typeHidden="2" opacity="178"/>
<arcSize val="30"/>
</element>
<expression label="kulmaOkTeksti" exp="" ✔️""/>
<element type="text" label="kulmaOkTeksti">
<show object="false" label="false" ev="40"/>
<condition showObject="kulmaOk ≟ 1"/>
<objColor r="0" g="0" b="0" alpha="0"/>
<layer val="0"/>
<labelMode val="0"/>
<fixed val="true"/>
<startPoint x="-3" y="-5.7" z="1"/>
</element>
<expression label="kulmannimi" exp=""""/>
<element type="text" label="kulmannimi">
<show object="false" label="true" ev="40"/>
</element>
<command name="Textfield">
<input a0="kulmannimi"/>
<output a0="textkulma"/>
</command>
<element type="textfield" label="textkulma">
<show object="true" label="true"/>
<objColor r="0" g="0" b="0" alpha="0"/>
<layer val="0"/>
<labelOffset x="69" y="158"/>
<labelMode val="3"/>
<fixed val="true"/>
<auxiliary val="true"/>
<startPoint number="0" x="-7" y="-5" z="1"/>
<startPoint x="-7" y="-5" z="1"/>
<linkedGeo exp="kulmannimi"/>
<length val="4"/>
<caption val="Kulma= "/>
</element>
<command name="If">
<input a0="kulmannimi ≟ "DEF"" a1="1" a2="0"/>
<output a0="kulmaOk"/>
</command>
<element type="numeric" label="kulmaOk">
<value val="0"/>
<symbolic val="true" />
<objColor r="0" g="0" b="0" alpha="0.1"/>
</element>
!!
-data: |!!
<geogebra format="5.0">
<euclidianView>
<coordSystem xZero="350" yZero="130" scale="25" yscale="25"/>
<axis id="0" show="false" />
<axis id="1" show="false" />
</euclidianView>
<kernel>
<decimals val="0"/>
<angleUnit val="degree"/>
</kernel>
</geogebra>
!!
```
- Tässä versiossa on tehty samat kuin edellisessä oli tehty kokonaan XML:llä, mutta tällä kertaa niin, että oliot on luotu komennoilla (
commands
) ja sitten olioiden ulkoasu on aseteltuobjxml
-attribuutilla. Tämä on kohtuullisen joustava tapa muutenkin muokata ulkoasua.
``` {plugin="csPlugin" #geoa3}
type: geogebra
#tool: true
stem: "Kirjoita kulman nimi pisteiden nimiä käyttäen"
-pointsRule:
expectCodePlain: "DEF"
width: 600
height: 320
commands: |!!
D = (-10, 0)
E = (0, -3)
h: Segment[D, E]
F = (7, 1)
i: Segment[E, F]
β: Angle[D, E, F]
kulmannimi: "DEF"
textkulma: Textfield[kulmannimi]
SetLabelMode(β,1)
SetColor(β,"Blue")
SetCoords(textkulma,0,260)
SetCaption(textkulma,"Kulma=")
!!
javascript: |!!
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
timgeo.setAllLabelsVisible(api, false); // kaikki labelit piiloon
api.setVisible("kulmannimi", false);
timgeo.setLabelsVisible(api, "D,E,F,β,textkulma", true); //muutamat takaisin
timgeo.setXmlProperty(api, 'textkulma', '<length val="5" />');
timgeo.setPointsCoords(api, geostate.userpts); // tilan palautus
api.evalCommand(geostate.usercmds);
}
P.getData = function(){
return {
"usercode": ggbApplet.getValueString('kulmannimi'),
"userpts": timgeo.getObjValue(ggbApplet,"D,E,F"),
"usercmds": timgeo.getObjCommand(ggbApplet, 'kulmannimi'),
};
}
!!
-data: |!!
<geogebra format="5.0">
<euclidianView>
<coordSystem xZero="350" yZero="130" scale="25" yscale="25"/>
<axis id="0" show="false" />
<axis id="1" show="false" />
</euclidianView>
<kernel>
<decimals val="0"/>
<angleUnit val="degree"/>
</kernel>
</geogebra>
!!
```
Tässä versiossa on riisuttu pois kaikki geoGebran puolella tapahtuva tarkistaminen ja kaikki kodi on siirretty joko komentoihin tai JavaScriptiin.
koska ei osattu komennoill atai JavaScriptiolla muuttaa syöttökentän leveyttä (joko voi korjata jos osaa), niin tämä on tehty muuttamalla olion XML-esitystä:
timgeo.setXmlProperty(api, 'textkulma', '<length val="5" />');
15.4 Monimutkaisempi arvostelu TIMin puolella
Palataan alkuperpäiseen kehäkulmatehtävään. Sen vikana on se, että osaava javaScript-käyttäjä voi lähettää oikean vastauksen selaimesta osaamatta mitään geometriasta. On varmempaa jos pisteet annetaan siitä, että piste C
on oikeassa paikassa. Alkuperäisessä tehtävässä pisteet A
ja B
olivat kiinnitetty joten periaatteesa pelkkä piste C
riittää laskukuihin. Siltä varalta että alkuperäisestä tehtävästä irrotettaisiin A
ja B
kiinnityksestään, tehdään tehtävä niin, että käyteään kaikkia kolmea pistettä kulman arvon laskemiseen ja tehdään laskeminen TIMin puolella. Koska tähän ei ole mitään valmista koodia, kirjoitetaan tarkistusfunktio itse käyttäen TIMin extrafiles
-attribuuttia.
``` {plugin="csPlugin" #angle60}
type: geogebra
stem: 'Säädä keskuskulma 60 asteeksi ja paina Tallenna'
filesaveattribute: userpts
-pointsRule:
readpoints: "Pisteet: (.*)\n"
filename: vastaus
cmd: "python3 arvostele.py vastaus.txt"
width: 650
height: 430
material_id: "j2axjgdc"
javascript: |!!
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
timgeo.setPointsCoords(api, geostate.userpts); // käyttäjän pisteiden paikat
}
P.getData = function(){
return {
"usercode": ggbApplet.getValueString('α'), // kulma tutkittavaksi
"userpts": timgeo.getObjValue(ggbApplet,"A,B,C"), // pisteet talteen
};
}
!!
-extrafiles:
-
name: arvostele.py
text: |!!
import sys
import re
import numpy as np
reprg = re.compile(' *([^ =]*) *= *[\\(\\[]([^,]*), *([^\\)\\]]*)')
def get_point(s):
global reprg
m = reprg.match(s)
return np.array([float(m[2]),float(m[3])])
lines = open(sys.argv[1], 'r').read().split("\n")
a = get_point(lines[0])
b = get_point(lines[1])
c = get_point(lines[2])
ba = b - a
ca = c - a
cosine_angle = np.dot(ba, ca) / (np.linalg.norm(ba) * np.linalg.norm(ca)) angle = np.arccos(cosine_angle)
asteet = round(np.degrees(angle))
pisteet = 0
viesti = "Et ihan onnistuntut"
if asteet == 60:
pisteet = 1
viesti = "Upeeta!"
print(viesti + " Pisteet: " + str(pisteet))
!!
```
16. Työkalu ggb, xml ja material_id käsittelyyn
Seuraavalla työkalulla voit käsitellä ggb ja xml tietoja.
Työkalun saat omalle sivullesi koodilla:
``` {plugin="csPlugin" #geotool}
type: geogebra
tool: true
```
Voit myös muuttaa olemassa olevan tehtäväsi tilapäisesti työkaluksi lisäämällä tool
-rivin.
16.1 Tyhjästä aloittaminen
Voit aloittaa työkalun käyttämisen tyhjästäkin muokkaamalla haluamallasi tavalla GeoGebra-pohjaa.
16.2 Tietojen lataaminen
Voit aloittaa myös lataamalla jonkin valmiin tehtävän ja tutkimalla/muokkaamalla sitä.
Selvitä jostakin
material_id
tai ggb-tiedoston osoite, Voit aloittaa kokeeksi vaikka material_id:lläX8EFduVc
Liitä id tai ggb-tiedoston nimi
Load
sanan vasemmalle puolellePaina
Load
16.3 ggb-datan tai XML-datan lataaminen
Voit aloittaa myös jos saat jostakin valmiin ggbBase64 datan tai XML-datan (voit kokeilla kopioida jonkin tässä ohjeessa aikaisemmin olleen datan pohjaksi).
- Liitä ggbBase64-data tai XML-data
Copy area
yläpuolella olevaan nimettömään data-laatikkoon. - Paina datan tyypin mukaan
Set Constraction
-rivillä jokoGGB
taiXML
16.4 Palaaminen aikaisemmin ladattuun tilanteeseen
Jos haluat erilaisten muutoskokeilujen jälkeen palata aikaisemmin GGB
tai Load
-toiminnolla alustamaasi tilanteeseen, niin paina Reset
.
16.5 Palaaminen tyhjään tilanteeseen
Jos haluat palata ihan tyhjään tilanteeseen, niin tyhjennä data-laatikko ja paina GGB
.
16.6 Tehtävän siirtäminen TIM-tehtäväksi
Kun olet saanut aikaiseksi halutunlaisen tehtävän niin sen saat siirrettyä TIMiin seuraavasti:
- Paina
Get constructions
-riville jokoGGB
taiXML
sen mukaan kummanko tyyppisenä haluat tehtävän siirtää TIMiin. - Paina
Copy area
(tosin saman voit tehdä maalaamalla data-laatikon ja valitsemalla kaikki ja sittenCtrl-C
) - Siirry TIM-dokumenttiin johon haluat laittaa tehtävän.
- Sopivaan TIM-pohjaan liitä
data:
riville (tai XML tapauksessadata: |!!
rivin jälkeen) leikepöydällä oleva data.
16.7 TIMissä olevan tehtävän muokkaaminen työkalulla
Jos haluat muokata TIMissä olevaa tehtävää työkalulla, niin toimi seuraavasti:
- Tyhjennä data-laatikko
- Paina
Set construction
-rivinGGB
jotta saat tehtävän ihan tyhjäksi. - Kopioi TIM-tehtävän
data:
sisältö data-laatikkoon. - Paina
Set construction
-rivillä datan sisällön mukaan jokoGGB
taiXML
- Muokkaa tehtävää.
- Siirrä tehtävän sisältö TIM-tehtäväksi aikaisemmilla ohjeilla.
17. Kaiken tekeminen HTML:llä
17.1 srchtml
Edellisten lisäksi voi halutessaan tehdä kaiken suoraan HTML:llä käyttäen srchtml
-attribuuttia
``` {plugin="csPlugin" #geohtml}
type: geogebra
path: user
srchtml: |!!
<!DOCTYPE html>
<html>
<head>
<title>Apps with Toolbar: Graphing Calculator</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div>
<script type="text/javascript" src="https://cdn.geogebra.org/apps/deployggb.js"></script>
<script type="text/javascript" src="/cs/geogebra/timgeo.js"></script>
<script type="text/javascript">
function perspective(p){
updateHelp(p);
ggbApplet.setPerspective(p);
}
var ggbApplet;
var P = {
"id":"ggbApplet",
//"appName":"graphing",
"width":800,
"height":420,
preventFocus: true,
//GEOMATERIALID
//GGBBASE64
//GEOFILENAME
//"showToolBar":true,
"borderColor":null,
//"showMenuBar":true,
//"allowStyleBar":true,
//"showAlgebraInput":true,
"customToolbar":"0 || 1",
"enableShiftDragZoom":true,
"capturingThreshold":null,
"errorDialogsActive":true,
//"showTutorialLink":true,
"showLogging":true,
preventFocus: true,
};
P.getData = function(){
return {"data": ggbApplet.getBase64()};
}
P.setDataInit = function (api, geostate) {
timgeo.setState(api, geostate);
}
P.setData = function(geostate) {
P.setDataInit(ggbApplet, geostate);
}
//GEOJAVASCRIPT
var geostate = GEOSTATE;
P.appletOnLoad = function(api) {
if ( !P.setDataInit ) return;
ggbApplet = api;
var g = atob(geostate);
var state = JSON.parse(g);
// timgeo.setState(api, state);
P.setDataInit(api, state);
}
var applet = new GGBApplet(P, '5.0', 'geogebra_container');
// when used with Math Apps Bundle, uncomment this:
// applet.setHTML5Codebase('GeoGebra/HTML5/5.0/web3d/');
window.onload = function() { applet.inject('geogebra_container');
}
function getData(){
if ( P.getData )
return P.getData();
}
function setData(geostate) {
if ( P.setData )
P.setData(geostate);
}
</script>
<div id="geogebra_container"></div>
</body>
</html>
!!
data: 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
```
Hyötynä tästä olisi että voi täysin itse säätää mitä missäkin näkyy. Voidaan periaattessa vaikka sijoittaa scrhtml
-attribuuttiin jokin valmis upotetun GeoGebran esimerkki. Tosin ilman muutoksia sen konstruktiota ei saada TIMiin talteen eikä opiskelijan vastauksia voi pisteyttää.
17.2 prehtml ja posthtml
Osan suoran HTML:än käytöstä saa käyttäen GeoGebra-komponentin attribuutteja:
prehtml: '<p>Tämä näkyy ennen komponenttia</p>'
posthtml: '<p>Tämä näkyy komponentin jälkeen</p>'
Näillä voi hyvin pitkälle muutella muutenkin mitä komponentin aluessa näkyy. Esimerkiksi voisi lisätä erilaisia ikoneita, joita näytetään erilaisista vastauksista.
Tosin näitä käyttäessä on usein syytä muuttaa vähintään komponenti korkeutta erikseen, sillä muuten noille teksteille ei jää tilaa:
``` {plugin="csPlugin" #geoprepost}
type: geogebra
height: 500
material_id: "X8EFduVc"
prehtml: '<p>Tämä näkyy ennen komponenttia</p>'
posthtml: '<p>Tämä näkyy komponentin jälkeen<p>'
javascript: |!!
P.height = 400;
!!
```
19. Yhteenveto TIMin GeoGebra-komponentin attribuuteista:
material_id
filename
width
height
javascript
prehtml
posthtml
data
commands
objxml
-pointsRule:
lazy
button
beforeOpen
open
showButton
srchtml
borders
lang
norun
These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.