A couple months ago one of our fellow-forum-members helped me a lot with building this Aircraft Recognition Quiz.
It is already fully operational in my school and I'm very happy with it, but I found some troubles with keeping it up to date because every picture has to be brought in manually. (it's about 1000pictures and it constantly evolves)
The website only consists of javascript, because I have to copy the "webtool" offline with my fellow-students and so I cannot teach everyone how to install a PHP-server. (I guess, I'm totally no pro! )
Now every picture has its adress and its value...
I wanted to know if I could let the browser pick a random picture from a folder and the value should then be the name of the folder. (or a name that I can still type in manually, but I should be great already if I can just drop pictures in a folder and so they will pop up in the quiz automaticly)
Is this possible with what I have already???
Thank you !
Here an example of how the website looks like at this moment:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Multiple Rocket Launcher Recognition</title>
/*
* Using difflib we are testing if is an approximation
*/
function IsApproximate (stCorrect, stAnswer)
{
var sm = new difflib.SequenceMatcher(stCorrect, stAnswer);
return sm.ratio();;
}
/* Create a new question
*/
function createQuestion()
{
totalQuestions++;
// Update Total Questions Label:
document.getElementById('questions').innerHTML = totalQuestions.toString();
// Prepare a new question Id:
questionId = Math.floor(Math.random() * testData.length);
document.getElementById('imageTest').src = testData[questionId][0];
}
/* Update Score Points
*/
function updateScore(points)
{
score+=points;
// Update Total Questions Label:
document.getElementById('score').innerHTML = score.toString();
}
/* Check Answer
*/
function checkAnswer(questionId)
{
// If we have an approximation we can let the user retry
var retry = false;
// Get the ratio approximation:
var ratio = IsApproximate (testData[questionId][1], document.getElementById('tekstregel').value.toLowerCase() );
// Response is Exact!
if ( ratio == 1 )
{
window.alert("Volledig juist!");
document.getElementById('tekstregel').value = "";
updateScore(1); // 1 points up in the score!
}
else if ( ratio > 0.7 ) // My limit to consider the answers Valid is 0.5 (must be adjusted!)
{
// I let him to retry, if it's an approximation (may be not infinitely )
retry = window.confirm("Probeer andere schrijfwijze, bijna juist!");
if ( retry == false) {
window.alert ("Correct Answer is: "+ testData[questionId][1]);
document.getElementById('tekstregel').value = "";
updateScore(1); // only 1 point up in score!
}
}
else
{
window.alert("Fout!\nHet juiste antwoord is: "+ testData[questionId][1]);
document.getElementById('tekstregel').value = "";
}
// If is retrying, don't generate new question
if ( retry == false )
createQuestion();
}
function keypressed(){
if(event.keyCode=='13'){checkAnswer(questionId);}
}
</script>
Here you can find what is in the difflib.js
I just got this from one of the forum's members...
I'm always open for input bus as I wasn't with Javascript, I'm not familiar with AJAX too...
I was just thinking about changing the adress from "folder/picture.jpg" to "folder/*" and then filling in the value still manually or if possible to use the foldername as value...
/***
This is part of jsdifflib v1.0. <http://snowtide.com/jsdifflib>
Copyright (c) 2007, Snowtide Informatics Systems, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the Snowtide Informatics Systems nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
difflib = {
defaultJunkFunction: function (c) {
return __whitespace.hasOwnProperty(c);
},
stripLinebreaks: function (str) { return str.replace(/^[\n\r]*|[\n\r]*$/g, ""); },
stringAsLines: function (str) {
var lfpos = str.indexOf("\n");
var crpos = str.indexOf("\r");
var linebreak = ((lfpos > -1 && crpos > -1) || crpos < 0) ? "\n" : "\r";
var lines = str.split(linebreak);
for (var i = 0; i < lines.length; i++) {
lines[i] = difflib.stripLinebreaks(lines[i]);
}
return lines;
},
// iteration-based reduce implementation
__reduce: function (func, list, initial) {
if (initial != null) {
var value = initial;
var idx = 0;
} else if (list) {
var value = list[0];
var idx = 1;
} else {
return null;
}
for (; idx < list.length; idx++) {
value = func(value, list[idx]);
}
return value;
},
// comparison function for sorting lists of numeric tuples
__ntuplecomp: function (a, b) {
var mlen = Math.max(a.length, b.length);
for (var i = 0; i < mlen; i++) {
if (a[i] < b[i]) return -1;
if (a[i] > b[i]) return 1;
}
// returns a function that returns true if a key passed to the returned function
// is in the dict (js object) provided to this function; replaces being able to
// carry around dict.has_key in python...
__isindict: function (dict) {
return function (key) { return dict.hasOwnProperty(key); };
},
// replacement for python's dict.get function -- need easy default values
__dictget: function (dict, key, defaultValue) {
return dict.hasOwnProperty(key) ? dict[key] : defaultValue;
},
SequenceMatcher: function (a, b, isjunk) {
this.set_seqs = function (a, b) {
this.set_seq1(a);
this.set_seq2(b);
}
this.set_seq1 = function (a) {
if (a == this.a) return;
this.a = a;
this.matching_blocks = this.opcodes = null;
}
this.__chain_b = function () {
var b = this.b;
var n = b.length;
var b2j = this.b2j = {};
var populardict = {};
for (var i = 0; i < b.length; i++) {
var elt = b[i];
if (b2j.hasOwnProperty(elt)) {
var indices = b2j[elt];
if (n >= 200 && indices.length * 100 > n) {
populardict[elt] = 1;
delete b2j[elt];
} else {
indices.push(i);
}
} else {
b2j[elt] = [i];
}
}
for (var elt in populardict) {
if (populardict.hasOwnProperty(elt)) {
delete b2j[elt];
}
}
var isjunk = this.isjunk;
var junkdict = {};
if (isjunk) {
for (var elt in populardict) {
if (populardict.hasOwnProperty(elt) && isjunk(elt)) {
junkdict[elt] = 1;
delete populardict[elt];
}
}
for (var elt in b2j) {
if (b2j.hasOwnProperty(elt) && isjunk(elt)) {
junkdict[elt] = 1;
delete b2j[elt];
}
}
}
this.find_longest_match = function (alo, ahi, blo, bhi) {
var a = this.a;
var b = this.b;
var b2j = this.b2j;
var isbjunk = this.isbjunk;
var besti = alo;
var bestj = blo;
var bestsize = 0;
var j = null;
var j2len = {};
var nothing = [];
for (var i = alo; i < ahi; i++) {
var newj2len = {};
var jdict = difflib.__dictget(b2j, a[i], nothing);
for (var jkey in jdict) {
if (jdict.hasOwnProperty(jkey)) {
j = jdict[jkey];
if (j < blo) continue;
if (j >= bhi) break;
newj2len[j] = k = difflib.__dictget(j2len, j - 1, 0) + 1;
if (k > bestsize) {
besti = i - k + 1;
bestj = j - k + 1;
bestsize = k;
}
}
}
j2len = newj2len;
}
this.get_matching_blocks = function () {
if (this.matching_blocks != null) return this.matching_blocks;
var la = this.a.length;
var lb = this.b.length;
var queue = [[0, la, 0, lb]];
var matching_blocks = [];
var alo, ahi, blo, bhi, qi, i, j, k, x;
while (queue.length) {
qi = queue.pop();
alo = qi[0];
ahi = qi[1];
blo = qi[2];
bhi = qi[3];
x = this.find_longest_match(alo, ahi, blo, bhi);
i = x[0];
j = x[1];
k = x[2];
if (k) {
matching_blocks.push(x);
if (alo < i && blo < j)
queue.push([alo, i, blo, j]);
if (i+k < ahi && j+k < bhi)
queue.push([i + k, ahi, j + k, bhi]);
}
}
Preface: I know nothing about what difflib.js does and don't plan on learning it.
However, if you need a way to select random images from different folders, the following may help.
If you know what images are in which folders and have a description for each image
the following assignments, as in the function getDescription1(), could be made for each different folder.
Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title> Untitled </title>
</head>
<body>
<div id="debugger"></div>
<script type="text/javascript">
function getDescription1(testImg) {
var folderInfo1 = { // similar setups for folderInfo2, folderInfo3, folderInfo4, .....
'1.jpg' : 'm270 mlrs',
'2.jpg' : 'm270 mlrs',
'3.jpg' : 'm270 mlrs',
'4.jpg' : 'bm-21',
'5.jpg' : 'bm-21',
'6.jpg' : 'bm-21',
'7.jpg' : 'rm-70',
'8.jpg' : 'rm-70',
'9.jpg' : 'rm-70',
'10.jpg' : '9p140',
'11.jpg' : '9p140',
'12.jpg' : '9p140',
'13.jpg' : '9p140 transloader',
'14.jpg' : '9p140 transloader',
'15.jpg' : '9p140 transloader',
'16.jpg' : '9a52 smerch',
'17.jpg' : '9a52 smerch',
'18.jpg' : '9a52 smerch',
'19.jpg' : '9a52 transloader',
'20.jpg' : '9a52 transloader',
'21.jpg' : '9a52 transloader' // Note: no comma after final entry
}[ testImg ];
return folderInfo1;
}
// Following from: http://danml.com/snips.htm
Array.prototype.shuffle=function(){
function Rnd(w) {return parseInt(Math.random() * (w + 1));}
var that= ([]).concat(this); var mx=that.length;
var r=[]; var mx2 = mx-1;
for(var i=0; i< mx; i++){
var slot= Rnd(mx2 - i );
r[i]=that.splice(slot , 1);
}
return r;
}//end shuffle
function imagesInFolder1(folderPath) {
var qarr = []; for (var i=1; i<=21; i++) { qarr[qarr.length] = i+'.jpg'; }
qarr = qarr.shuffle(); // can scramble array as needed
var str = '';
for (var i=0; i<qarr.length; i++) { str += folderPath+' has '+getDescription1(qarr[i])+'<br>'; }
document.getElementById('debugger').innerHTML = str;
// return folderPath+'/'+folderInfo1[resp]; // if only one selection is needed
}
window.onload = function() { imagesInFolder1('folder1'); }
</script>
</body>
</html>
If you need further explaining as to what I'm suggesting and how to use it in your quiz, just ask.
You will need to provide a link to your images (and path) along with your quiz code.
BTW: You should put your script code between [ code] and [ /code] tags (without the spaces)
to make it easier to read, copy, test and debug by other forum members. It also retains your formatting.
Okay, and what if I should start using a database?
At first I thought not to do it because the website would not be available online, but maybe it is an option!
I've put a small part of the website online here: www.driesgovaerts.be/heverlee/reco.html
Can anyone help me about how I can make this different categories in the quiz easier to update? Using a random picture from each folder (automaticly) naming it the foldername OR rebuilding it using a database where I can just drop pictures/folders and automaticly having it a value given?
Because as I said, I have to give now each individual picture an adress and I have to give each individual picture a value too... (using javascript, ...) But I have more than 1000pictures and a lot of these pictures have the same value.
I just want to keep the same layout and I'm not very familiar with PHP and databases, but I always want to try it...
Is there anyone that can send me a tutorial or something about how to set up a database and how I should integrate in into my website? Me and my class will be very gratefull...
Here is a way to not need to use a database unless the images are not sequential or in individual directories
which you seem to imply they are by the code provided in the link of the last post.
There are TWO example of how the array could be set-up. Even if they are not sequential, the first array
could be modified by specifying the correct file names for the appropriate answer.
Note also that the directory selection could also be randomized with a bit of forthought.
Code:
<html>
<body>
<table border="1" width=50%">
<tr>
<td width="50%"> <div id="debugger1"></div> </td>
<td width="50%"> <div id="debugger2"></div>
</tr>
<tr>
<th><button onclick="testDisplay()">Test Display 1</button> </th>
<th> <button onclick="displayTest()">Display Test 2</button> </th>
</tr>
</table>
<script type="text/javascript">
// Suggested modifications for: http://www.webdeveloper.com/forum/showthread.php?273241-Aircraft-recognition-quiz&daysprune=30
var testData = [ ['uh-1 iroquois', '361','362','363','364','365'], // 5 images 361.jpg, 362.jpg, 363.jpg, 364.jpg, 365.jpg
['uh-60 black hawk', '366','367','368','369','370'],
['mi-8/17 hip', '371','372','373','374','375'],
['mi-14 haze', '376','377','378','379','380'],
['ch-53 stallion', '381','372','373','374','375'],
['puma', '386','377','378','379','390'],
['nh-90', '391','392','393','394','395'],
['aw101 merlin', '396','397','398','399','400'],
['mi-6 hook', '401','402','403','404','405'],
['mi-26 halo', '406','407','408','409','410'],
['sea king', '411','412','413','414','415'],
['gazelle', '416','417','418','419','420'],
['dauphin - panther', '421','422','423','424','435'],
['ch-46 sea knight', '426','427','428','429','430'],
['ch-47 chinook', '431','432','433','434','445'],
['a-109', '436','437','438','439','440'],
['lynx', '441','442','443','444','455'],
['mi-24 hind', '446','447','448','449','450'],
['mi-28 havoc', '451','452','453','454','465'],
['ah-1 cobra', '456','457','458','459','460'],
['ah-64 apache', '461','462','463','464','475'],
['tiger', '466','467','468','469','470'],
['a-129 mangusta', '471','472','473','474','485'],
['ka-50/52 hokum', '476','477','478','479','480'],
['ka-25 hormone', '481','482','483','484','495'],
['ka-27 helix', '486','487','488','489','490'],
['md 500 defender', '491','492','493','494','495'],
['bo-105', '496','497','498','499','500'],
['oh-58 kiowa', '501','502','503','504','505'] // No comma after final entry
];
function testDisplay() {
// http://www.driesgovaerts.be/heverlee/aircraft
imgDirs = './'; // ['./d1/','./d2/','./d3/']; // could select one of these with addition of some random pick logic
var q = Math.floor(Math.random()*testData.length); // form random question #
var qp = Math.floor(Math.random()*5); // form random question picture
var pix = imgDirs+testData[q][qp+1]+'.jpg'; // get image to display
var ans = testData[q][0]; // remember answer to question
var tarr = [];
tarr.push('Random Question: '+q);
tarr.push('Random Picture : '+qp);
tarr.push('Image : '+pix);
tarr.push('Answer: '+ans);
var obj = document.getElementById('debugger1');
obj.innerHTML = tarr.join('<br>');
}
var dataTest = [ ['uh-1 iroquois', '361'], // 5 images starting at 361.jpg, 362.jpg, 363.jpg, 364.jpg, 365.jpg
['uh-60 black hawk', '366'],
['mi-8/17 hip', '371'],
['mi-14 haze', '376'],
['ch-53 stallion', '381'],
['puma', '386'],
['nh-90', '391'],
['aw101 merlin', '396'],
['mi-6 hook', '401'],
['mi-26 halo', '406'],
['sea king', '411'],
['gazelle', '416'],
['dauphin - panther', '421'],
['ch-46 sea knight', '426'],
['ch-47 chinook', '431'],
['a-109', '436'],
['lynx', '441'],
['mi-24 hind', '446'],
['mi-28 havoc', '451'],
['ah-64 apache', '461'],
['tiger', '466'],
['a-129 mangusta', '471'],
['ka-50/52 hokum', '476'],
['ka-25 hormone', '481'],
['ka-27 helix', '486'],
['md 500 defender', '491'],
['bo-105', '496'],
['oh-58 kiowa', '501'] // No comma after final entry
];
function displayTest() {
imgDirs = './'; // ['./d1/','./d2/','./d3/']; // could select one of these with addition of some random pick logic
var q = Math.floor(Math.random()*dataTest.length); // form random question #
var qp = Math.floor(Math.random()*5); // form random question picture
var img = (Number(dataTest[q][1])+qp)+'.jpg'; // add random # to base for picture to display
var pix = imgDirs+img; // get image to display
var ans = dataTest[q][0]; // remember answer to question
var tarr = [];
tarr.push('Random Question: '+q);
tarr.push('Random Picture : '+qp);
tarr.push('Image : '+pix);
tarr.push('Answer: '+ans);
var obj = document.getElementById('debugger2');
obj.innerHTML = tarr.join('<br>');
}
</script>
</body>
</html>
Another concept you could apply would be to place all your filenames into a text file and read that file
from a server using some ajax code added. This would require an internet connection while the previous
example above could be executed from a local file. Your design choice.
The filenames could be created with a simple UNIX command on the server
Something like: ls -1 > imgFile1.txt and then modified with your answer key to form the formatted arrays.
Bookmarks