SlideShare a Scribd company logo
1 of 123
Download to read offline
SWAD, an Open
Learning Management System
Including timeline implementation
Antonio Cañas
University of Granada (UGR)
@acanasvargas acanas@ugr.es acanas@openswad.org
https://openswad.org/ @openswad
SWAD, an Open
Learning Management System
Including timeline implementation
Antonio Cañas
University of Granada (UGR)
@acanasvargas acanas@ugr.es acanas@openswad.org
https://openswad.org/ @openswad
1
1
Antonio Cañas et al.
November 22 2021, Granada, Spain
November 22 2021, Granada, Spain
Contents
●
History and summary of features
●
Implementation
●
Free software release
●
swad.ugr.es figures
●
openswad.org
●
Future objectives and tasks
●
Conclusions
History and
summary of features
“The dream of yesterday is the hope of today and the
reality of tomorrow”
.
Robert H. Goddard
History and
summary of features
“The dream of yesterday is the hope of today and the
reality of tomorrow”
.
Robert H. Goddard
LMS in 2021: a very broad offer
●
Today: hundreds of LMS
●
proprietary / free software
●
expensive / free of charge
●
installable on the client's servers / accessible in the cloud
LMS in 2021: a very broad offer
308
LMS in 2021: a very broad offer
619
...but in 1999 there were not so many available, and we
started to develop our own system:
Sistema Web de Apoyo a la Docencia
(Web System for Teaching Support)
⬇
Social Workspace At a Distance
https://swad.ugr.es/
https://openswad.org/
A web platform to manage courses, students and teachers,
with functions to support teaching and learning.
What is SWAD?
This is how it looks,
although some parts of its appearance,
such as colors or icons, are customizable
What is SWAD?
Features
Free software · 9 languages · Responsive design · Android app
Face-to-face or blended learning
Hierarchical organization: System · Countries · Institutions
(universities, companies) · Centers (faculties, schools) ·
Degrees · Courses · Group types · Groups
10 available roles: Unknown · Guest · User · Student · Non-
editing teacher · Teacher · Degree admin · Center admin ·
Institution admin · System admin
Functionality
Social network · Calendar · Notifications · Course
information · Syllabus · Documents · Shared files ·
Portfolio · Grades · Assignments · Projects · Exam
announcements · Quizzes · Exams · Games · Surveys ·
Groups · Lists of students and teachers · Attendance
control using QR codes · Forums · Notices · Messaging
system · Statistics · Agenda · Preferences
All features in
https://github.com/acanas/swad-core/wiki/UserGuide.en
Dpt.ATC: 1999-2003
1º TIP: 2003-2004
2º TIP: 2005-2006
3º TIP: 2006-2008
V.L.Center:2008-2016
Free Software: 2010...
UNA.py: 2012-2014
OpenSWAD: 2012…
Dpt.ATC: 2016...
21 years of use and development
openswad.org
2012...
ugr.es CEVUG
2008-2016
ugr.es TIPs
2003-2008
ugr.es ATC
1999-2003
una.py
2012-2015
ugr.es ATC
2016...
Free software release
“You're frozen
When your heart's not open”
Frozen, Madonna
Free software release
“You're frozen
When your heart's not open”
Frozen, Madonna
First release as free software
January 21, 2010
Free software office of the University of Granada
Steps to release the core
1. Code (names, comments) in English (100%)
2. Code independent from the UGR (100%)
3. Translation to 9 languages (90%)
4. Add AGPL headers to files (100%)
5. Publish the source code (100%) https://openswad.org/source/
6. Publish the installation procedure (100%) https://openswad.org/install/
7. Use git version control system (100%)
8. Upload to GitHub (100%) https://github.com/acanas/swad-core
9. Desirable: automate installation (20%)
Why do we create free software?
●
Because it facilitates collaborative development
Fourth Hackathon of free software projects of the UGR, 2012. Photo: A. Cañas
Why do we create free software?
●
Because it encourages better programming
@psicobyte_ explains the benefits of free software. Photo: A. Cañas
Why do we create free software?
●
Because it improves the code quality
Hackathon of SWADroid and SWAD, 2013. Photo: A. Cañas
Why do we create free software?
●
Because it provides freedom and security to users
https://www.gnu.org/philosophy/
How much work is behind?
swad-core SWADroid
Affero GPL v3 license
https://github.com/acanas/swad-core
GPL v3 license
https://github.com/Amab/SWADroid
361,650
C code lines
144
MySQL tables
60,744
Java code lines
17K
downloads
94 person-years
estimated effort*
14 person-years
estimated effort*
$5,196,470
estimated cost*
$794,070
estimated cost*
Other modules and more info: https://openswad.org/source
* According to the COCOMO model in Open Hub
swad.ugr.es figures
“What goes up,
must come down”
What goes up, The Alan Parsons Project
swad.ugr.es figures
“What goes up,
must come down”
What goes up, The Alan Parsons Project
482 million
clicks (page views)
386
million
(80%)
students
26
million
(5%)
teachers
69
million
(14%)
others
1
million
(<1%)
admin.
SWAD-UGR - Jan 2005 Nov
→ 2021
198,402
users have used the platform
173,814
(88%)
as students
3913
(2%)
as teachers
35,677
(18%)
as guests
133
(<1%)
as admin.
SWAD-UGR - Jan 2005 Nov
→ 2021
2,0million
messages sent
21,3million
messages received
SWAD-UGR - Jan 2005 Nov
→ 2021
154,736
current users
129,352
(84%)
students
3636
(2%)
teachers
22,181
(14%)
guests
119
(<1%)
admin.
SWAD-UGR - Nov 2021
...from 1089institutions
ugr
114,774
(74%)
from UGR
11,186
(3%)
from other institutions
28,776
(22%)
unknown
531
degrees
7646
courses
SWAD-UGR - Nov 2021
822,749 (1.8 TB)
files
46,127
test questions
1399
forums
24 million
times answered
66,520
posts
SWAD-UGR - Nov 2021
Courses (swad.ugr.es)
7646 courses
5092 with students
Teachers (swad.ugr.es)
3636 teachers
(100% of 3621)
Students (swad.ugr.es)
129,352 students
>100%
Real users / academic year (swad.ugr.es)
Page views / week (swad.ugr.es)
Users / week (swad.ugr.es)
Keys to success at the UGR
●
#1: Platform open to the entire University since 2004
I Meeting of SWAD Users
Keys to success at the UGR
●
#2: Teacher training
Keys to success at the UGR
●
#3: User support: thousands of queries answered
Thank you for your help and efficiency...
and for having designed a computer invention that really works,
which reconciles me with the new technologies...
●
#4: Developed according to the users’ requests
Keys to success at the UGR
A user wants the platform
to congratulate him
on his birthday...
Days later a new feature
congratulates users
for their birthdays.
Keys to success at the UGR
●
#5: Strengths of the tool
●
Functionality and usability
●
Simplicity
●
It has what most teachers asked
●
Reliability and safety
●
It consumes few resources
●
It works 24 hours, fast and almost without failures
openswad.org
“A planet is the cradle of mind, but one cannot live in
a cradle forever.”
Konstantin Tsiolkovski (russian physicist)
openswad.org
“A planet is the cradle of mind, but one cannot live in
a cradle forever.”
Konstantin Tsiolkovski (russian physicist)
SWAD outside the UGR after release
●
Little diffusion
●
Difficult to reach the target audience (need for advertising)
●
Absence of simple installation
●
Many competitors
●
Many LMS, some of them very widespread
●
Released as free software too late (2010)
●
A lot of work, small team
●
Conclusion
●
Very few (two or three) installations
The OpenSWAD.org project
●
OpenSWAD.org is an installation in the cloud of the
SWAD educational platform, offered free of charge for
any country by the OpenSWAD Association (non-profit
organization, independent of the UGR)
●
OpenSWAD.org is available since 2012, but it did not start
growing until 2015, when we decided to carry out
advertising campaigns
Why “Open”?
●
Free software (so open source)
●
Open and free for everyone
●
Open design and interaction
●
You can access many features (hierarchy, courses, teachers, statistics) even
if you are not logged in
●
Open content allowed
●
Upload, mark as public and choose license
●
Anyone could access, even without log in
Steps for internationalization
1. Code independent from the institution (100%)
2. Translation to 9 languages (90%)
3. ISO 8601 format for date-times (100%)
4. Dates-hours independent of location (100%)
5. Calendars independent of location (100%)
6. Weeks starting on Monday or Sunday (100%)
7. Floating point / comma format (10%)
Advertising: conversion funnel
2,600,000 ad impressions on Twitter and Facebook
2,600,000 ad impressions on Twitter and Facebook
2600 filled in their data (50%)
2600 filled in their data (50%)
260 created center, degree, course (10%)
260 created center, degree, course (10%)
130,000 clicked link (5%)
130,000 clicked link (5%)
5200 created account (
5200 created account (4%
4%)
)
130 enrolled in course (50%)
130 enrolled in course (50%)
65 created course content (50%)
65 created course content (50%)
13 used with students (20%, 5 per million)
13 used with students (20%, 5 per million)
Example: Feb. 2015 March 2016
→
Cost of advertising (2015 2017)
→
Cost Dates Days Cost/day Impressions Clicks Cost/click
Twitter 4650.29€ Feb 12, 2015
Sep 25, 2017
956 4.86 € 14,042,284 50,119 €0.108
Facebook 2400.84€ Sep 26, 2015
Sep 25, 2017
730 3.29 € 12,858,591 192,833 €0.012
AdWords 1255.93€ Feb 16, 2017
Sep 25, 2017
221 5.68 € 392,298 15,046 €0.083
Total 8307.06€ Feb 12, 2015
Sep 25, 2017
956 8.69 € 27,293,173 257,998 €0.032
Courses Teachers Students Total users
Courses or users with real use 528 385 1657 18 411
Cost per course or user €15,73 €21,58 €5,01 €0,45
Conversion comparison (2017)
Cost Dates Days Impresiones Clicks Page views Users New
accounts
New
courses
Twitter €66.20 Sep 6 -
Sep 24,
2017
7
€9.46 /
day
271,072
€0.00024 /
impression
734
€0.09 /
click
14 632
€0.0045 /
page view
342
€0.19 /
user
186
€0.36 /
new
account
10
€6.62 /
new
course
Facebook €109.66 Sep 7 -
Sep 25,
2017
7
€15.66 /
day
148,206
€0.00074 /
impression
3780
€0.03 /
click
33 087
€0.0033 /
page view
274
€0.40 /
user
114
€0.96 /
new
account
12
€9.14 /
new
course
AdWords €65.83 Sep 5 -
Sep 23,
2017
7
€9.40 /
day
13,210
€0.00498 /
impression
808
€0.08 /
click
11 169
€0.0060 /
page view
243
€0.27 /
user
94
€0.70 /
new
account
7
€9.40 /
new
course
Total €241.69 Sep 5 -
Sep 25,
2017
21
€11.51 /
day
432,488
€0.00056 /
impression
5322
€0.05 /
click
58 888
€0.0041 /
page view
859
€0.28 /
user
394
€0.61 /
new
account
29
€8.33 /
new
course
5,3million
clicks (page views)
1,553,800
(29%)
students
806,015
(15%)
teachers
2,625,210
(50%)
others
317,727
(6%)
admin.
OpenSWAD - Jan 2014 Nov 2021
→
34,440
current users
5566
(16%)
students
1911
(6%)
teachers
27,291
(79%)
guests
149
(<1%)
admin.
OpenSWAD - Nov 2021
from 152
countries
from 2141
institutions
23,557
institutions
2589
centers
2924
degrees
4460
courses
OpenSWAD - Nov 2021
Users / country (OpenSWAD)
First countries in OpenSWAD according to number of users
First countries in OpenSWAD according to number of users
34,440 users
from 152 countries
Users / country (OpenSWAD)
●
Even a report about OpenSWAD has been broadcast on a
Latin American TV channel
OpenSWAD in Atomun, Telesur TV (Venezuela), July 2017
Users / institution (OpenSWAD)
Users from 2924 institutions
Users / month 2014 2021 (OpenSWAD)
→
Advertisements
Teachers / month 2014 2021 (OpenSWAD)
→
Advertisements
Students / month 2014 2021 (OpenSWAD)
→
Advertisements
Implementation
“Every step that you take
Could be your biggest mistake
It could bend or it could break
That's the risk that you take”
What If, Coldplay
Implementation
“Every step that you take
Could be your biggest mistake
It could bend or it could break
That's the risk that you take”
What If, Coldplay
The core
●
Written from scratch in C
(compiled, not interpreted)
✔Advantages:
●
+ speed
●
- memory
●
Functional even in a Raspberry Pi
●
+ stability of source code over time
✘Disadvantages:
●
absence of specialized library
functions for the web
Former servers at the UGR
2nd: 2004-2006
Pentium 4 HT
RAM 2 GiB
2 HD 160 GB
Fedora 3
3rd: 2007-2008
Core 2 Duo
RAM 4 GiB
2 HD 500 GB
Fedora 6
4th: 2009-2010
Core 2 Quad
RAM 4 GiB
2 HD 146 GB
2 HD 1 TB
Fedora 10
5th: 2011-2016
2 Xeon Quad
RAM 24 GiB
4 HD 146 GB
4 HD 500 GB
CentOS 5.7
1st: 1999-2003
Shared server
Current server at the UGR (6th: 2016...)
●
HP Proliant DL160 G9, 2 Xeon with 6 cores, RAM 32 GiB
4 HD 146 GB
SAS 15000 rpm
RAID 1+0 (292 GB)
SO CentOS 7.2
MySQL database
4 HD 1 TB
SAS 7200 rpm
RAID 5 (3 TB)
Web files
( /var/www )
Plugins
●
It is possible to develop add-ons (plugins) that run on:
●
other servers
●
mobile devices. Example: SWADroid
●
The plugins interact with the swad core through an API:
https://openswad.org/api/
Photographs of users
●
Our own automatic system for detecting faces and
improving the quality of photos, trained with 90K photos
Up to 400K times per day
Up to 2000 times / minute (30 times / second)
Log
“click”
logged access
HTML
server
database
swad-core
144 database tables.
The largest is the one
used to store the access log.
Database
Log table
●
It allows analyzing a lot of information:
●
By role
●
By user
●
By action performed
●
By qualification
●
By subject
●
By dates
●
...
UGR: 482 million registered hits since 2005
Log table
Pages per minute
(averaged during an academic year)
teachers
students
Log table
Matches of the Soccer World Cup 2010
You can even see the rest in the match
Log table
Peak: students choosing groups
Page views per minute
Log table
●
What if we convert every click into a sound?
●
At 1 am:
http://swad.ugr.es/stat/clicks/clicks_1am.wav
●
At 1 pm:
http://swad.ugr.es/stat/clicks/clicks_1pm.wav
●
Peak (students choosing groups):
http://swad.ugr.es/stat/clicks/clicks_grupos.wav
Who has developed it?
●
Recent programmers:
●
Antonio Cañas Vargas (swad-core, servers, management, courses)
●
Daniel J. Calandria Hernández (photo processing, chat)
●
Juan Miguel Boyero Corral (SWADroid)
●
Adrián Lara Roldán (iSWAD)
●
Jesús Mesa González (photo processing)
●
Sergio Díaz Rueda (SWADroid)
(green = free software)
Who has developed it?
●
Former programmers (I):
●
Jesús Álvarez Martín (photo processing)
●
Alberto E. Rodrigo Gámiz (photo processing)
●
Ana Belén Cara Carmona (chat & whiteboard)
●
Carlos Moreno Muñoz (chat & whiteboard)
Who has developed it?
●
Former programmers (II):
●
Antonio Manuel Aguilera Malagón (SWADroid)
●
Helena Rodríguez Gijón (SWADroid)
●
José Antonio Guerrero Avilés (SWADroid)
●
Alejandro Alcalde Barros (SWADroid)
●
Rubén Martín Hidalgo (SWADroid)
●
Miguel Ángel Cerrailo Valle (Triswados, app Android)
●
Raúl Álvarez Hinojosa (iSWAD)
Who has developed it?
●
Programmers of modules that were not used:
●
Andrés Ramón Masegosa Aredondo (photo processing)
●
Raúl Jiménez Benítez (chat)
●
María Beatriz Medina Yáñez (whiteboard)
●
Raquel Cazalilla Sáez (chat & whiteboard)
●
Emiliano Luis Rincón Vallejos (rich text editor)
●
Diego Montesinos Hervás (iSWAD)
●
Lucas Ortiz Velasco (SWADMyPage)
●
David Medina Godoy (SWADE, rich text editor)
●
Marta Muñoz López (SWAD2Moodle)
Who has developed it?
●
Translators:
●
Antonio Cañas Vargas (CA,DE,EN,ES,FR,GN,IT,PL,PT)
●
Joan Lluís Díaz Rodríguez (CA)
●
Rafael Barranco Droege (DE)
●
Giuseppe Antonio Pagin, Antonella Grande, Francisco Manuel
Herrero Pérez, Nicola Comunale Rizzo (IT)
●
Wojtek Kieca, Tomasz Olechowski, Mateusz Stanko (PL)
Who has developed it?
●
Contributors (I):
●
Javier Fernández Baldomero (forums, papers)
●
Antonio F. Díaz García (servers)
●
Eva Martínez Ortigosa (administration, papers)
●
Francisco Illeras García (servers)
●
Alberto Prieto Espinosa (papers)
●
Beatriz Prieto Campos (papers)
●
Begoña del Pino Prieto (papers)
●
Mancia Anguita López (papers)
●
Eduardo Ros Vidal (papers)
Who has developed it?
●
Contributors (II):
●
Francisco A. Ocaña Lara (FAQ, papers)
●
Adrián Gómez Anaya (WikiSwad)
●
Paloma Marín Arraiza (video tutorials)
●
technicians and scholars from the Virtual Learning Center
●
~120 degree administrators
●
...and many more
Timeline
“You think you know when you learn, are more sure
when you can write, even more when you can teach,
but certain when you can program.”
Alan Perlis
Timeline
“You think you know when you learn, are more sure
when you can write, even more when you can teach,
but certain when you can program.”
Alan Perlis
Timeline, notes, publications
●
Timeline: set of publications
●
from a user
●
global
●
Only me
●
Followed users
●
All users
typedef enum
{
Tml_Usr_TIMELINE_USR,
Tml_Usr_TIMELINE_GBL,
} Tml_Usr_UsrOrGbl_t;
typedef enum
{
Usr_WHO_UNKNOWN,
Usr_WHO_ME,
Usr_WHO_SELECTED, // Not applicable to timeline
Usr_WHO_FOLLOWED,
Usr_WHO_ALL,
} Usr_Who_t;
Timeline, notes, publications
●
Publication: · original note (24805, 78% of 31845)
· shared note ( 1282, 4% of 31845)
· comment to a note ( 5758, 18% of 31845)
struct Tml_Pub_Publication
{
long PubCod; // Publication code
long NotCod; // Note code
long PublisherCod; // Sharer or writer of the publication
Tml_Pub_Type_t Type; // Original note, shared note, comment
struct Tml_Pub_Publication *Next; // Used for chained list
};
*swad.ugr.es, nov 2021
Timeline, notes, publications
●
Note: timeline post ( 4163, 17% of 24805)
public file ( 66, <1% of 24805)
call for exam ( 2727, 11% of 24805)
notice (17567, 71% of 24805)
forum post ( 282, 1% of 24805)
*swad.ugr.es, nov 2021
Timeline, notes, publications
struct Tml_Not_Note
{
long NotCod; // Unique code/identifier for each note
Tml_Not_Type_t Type; // Timeline post, public file,
// call for exam, notice, forum post...
long UsrCod; // Publisher
long HieCod; // Hierarchy code
// (institution/center/degree/course)
long Cod; // Code of file, forum post,
// notice, timeline post...
bool Unavailable; // File, forum post, notice,...
// unavailable (removed)
time_t DateTimeUTC; // Date-time of publication in UTC time
unsigned NumShared; // Number of times (users)
// this note has been shared
unsigned NumFavs; // Number of times (users)
// this note has been favourited
};
Timeline, notes, publications
__________________
|@author |
| Note |
|__________________|
|@author |
| Comment 1 |
|______________|
|@author |
| Comment 2 |
|______________|
| |
| ... |
|______________|
|@author |
| Comment n |
|______________|
●
A note can have comments attached to it:
Timeline, notes, publications
_tml_pubs______ _tml_comments
| | | |
| Publication p |---------->| Comment c |-----+
| (comment) | | (to note 2) | |
|_______________| |_____________| |
| | | | |
· ... · · ... · |
· ... · · ... · |
|_______________| |_____________| |
| | | | |
|Publication i+4|---------->| Comment 1 |---+ |
| (comment) | | (to note n) | | |
|_______________| |_____________| | |
| | (4855) | |
|Publication i+3|-- | |
|(original note)|  | |
|_______________|  _tml_notes_____ | | _cfe_exams_____
| |  | | | | | |
|Publication i+2|-- ---->| Note n |<-+ | | Call for exam | (5581)
|(original note)|  |(exam announc.)|-(2622)->|_______________|
|_______________|  |_______________| 11% __brw_files____
| |  | | | | |
|Publication i+1|-- ---->| Note n-1 |-(64)--->| Public file | (1497132)
|(original note)|  | (public file) | <1% |_______________|
|_______________|  |_______________| | _not_notices___
| |  | | | | |
| Publication i |-- ---->| Note n-2 |-(17078)>| Notice | (14984)
|(original note)|  | (notice) | 72% |_______________|
|_______________|  |_______________| | __tml_posts____
| |  | | | | |
· ... · ---->| Note n-3 |-(3533)->| Post s |
· ... · | (tl. post) | 15% | |
|_______________| |_______________| | |_______________|
| | | | | | |
| Publication 3 | · ... · | · ... · (3533)
| (shared note) |--- · ... · | · ... ·
|_______________|  |_______________| | |_______________|
| |  | | | | |
| Publication 2 | ---->| Note 2 |<---+ | Post 1 |
|(original note)|--------->| (tl. post) |-------->| |
|_______________| |_______________| |_______________|
| | | | _for_posts_____
| Publication 1 |--------->| Note 1 | | |
|(original note)| | (forum post) |-(276)-->| Forum post | (66226)
|_______________| |_______________| 1% |_______________|
(29435) (23573)
timeline posts
public files
calls for exams
notices
forum posts
notes
comments
publications
144 database tables.
The largest is the one
used to store the access log.
Database
Database
mysql> SHOW TABLES LIKE 'tml_%';
+------------------------+
| Tables_in_swad (tml_%) |
+------------------------+
| tml_comments |
| tml_comments_fav |
| tml_notes |
| tml_notes_fav |
| tml_posts |
| tml_pubs |
| tml_timelines |
+------------------------+
7 rows in set (0.00 sec)
Database: publications
mysql> DESCRIBE tml_pubs;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| PubCod | bigint | NO | PRI | NULL | auto_increment |
| NotCod | bigint | NO | MUL | NULL | |
| PublisherCod | int | NO | MUL | NULL | |
| PubType | tinyint | NO | MUL | NULL | |
| TimePublish | datetime | NO | MUL | NULL | |
+--------------+----------+------+-----+---------+----------------+
Database: notes
mysql> DESCRIBE tml_notes;
+-------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+----------------+
| NotCod | bigint | NO | PRI | NULL | auto_increment |
| NoteType | tinyint | NO | MUL | NULL | |
| Cod | int | NO | | -1 | |
| UsrCod | int | NO | MUL | NULL | |
| HieCod | int | NO | | -1 | |
| Unavailable | enum('N','Y') | NO | | N | |
| TimeNote | datetime | NO | MUL | NULL | |
+-------------+---------------+------+-----+---------+----------------+
mysql> DESCRIBE tml_notes_fav;
+---------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+----------+------+-----+---------+----------------+
| FavCod | bigint | NO | PRI | NULL | auto_increment |
| NotCod | bigint | NO | MUL | NULL | |
| UsrCod | int | NO | MUL | NULL | |
| TimeFav | datetime | NO | | NULL | |
+---------+----------+------+-----+---------+----------------+
Database: comments
mysql> DESCRIBE tml_comments;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| PubCod | bigint | NO | PRI | NULL | |
| Txt | longtext | NO | MUL | NULL | |
| MedCod | int | NO | MUL | -1 | |
+--------+----------+------+-----+---------+-------+
mysql> DESCRIBE tml_comments_fav;
+---------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+----------+------+-----+---------+----------------+
| FavCod | bigint | NO | PRI | NULL | auto_increment |
| PubCod | bigint | NO | MUL | NULL | |
| UsrCod | int | NO | MUL | NULL | |
| TimeFav | datetime | NO | | NULL | |
+---------+----------+------+-----+---------+----------------+
Database: posts
mysql> DESCRIBE tml_posts;
+--------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+----------------+
| PstCod | int | NO | PRI | NULL | auto_increment |
| Txt | longtext | NO | MUL | NULL | |
| MedCod | int | NO | MUL | -1 | |
+--------+----------+------+-----+---------+----------------+
mysql> DESCRIBE cfe_exams;
+-------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+----------------+
| ExaCod | int | NO | PRI | NULL | auto_increment |
| ... | ... | ... | ... | ... | ... |
mysql> DESCRIBE brw_files;
+-----------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------+------+-----+---------+----------------+
| FilCod | int | NO | PRI | NULL | auto_increment |
| ... | ... | ... | ... | ... | ... |
mysql> DESCRIBE not_notices;
+-----------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+----------------+
| NotCod | int | NO | PRI | NULL | auto_increment |
| ... | ... | ... | ... | ... | ... |
mysql> DESCRIBE for_posts;
+-----------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+----------------+
| PstCod | int | NO | PRI | NULL | auto_increment |
| ... | ... | ... | ... | ... | ... |
Database: timelines
mysql> DESCRIBE tml_timelines;
+-----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+-------+
| SessionId | char(43) | NO | PRI | NULL | |
| NotCod | bigint | NO | PRI | NULL | |
+-----------+----------+------+-----+---------+-------+
mysql> DESCRIBE tml_tmp_timeline;
+--------+--------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------+------+-----+---------+-------+
| NotCod | bigint | NO | PRI | NULL | NULL |
+--------+--------+------+-----+---------+-------+
Timeline: getting list of publications
●
Our algorithm:
●
Select publications one by one in a loop
●
In each iteration:
●
Get the most recent publication (original, shared or comment) checking
that its note is not already retrieved
●
After getting a publication, save its note code to not get it again.
SELECT PubCod
FROM tml_pubs
WHERE NotCod NOT IN
(SELECT NotCod
FROM tml_tmp_timeline)
ORDER BY PubCod DESC
LIMIT 1;
Timeline: getting list of publications
●
Slower alternative (may need seconds for large tables):
●
Get the maximum PubCod, i.e more recent publication (original,
shared or commment), of every set of publications corresponding
to the same note:
SELECT MAX(PubCod) AS NewestPubCod
FROM tml_pubs
GROUP BY NotCod
ORDER BY NewestPubCod DESC
LIMIT 10;
Timeline: getting list of publications
●
Restricting publications to mine and those I follow:
CREATE TEMPORARY TABLE fol_tmp_me_and_followed
(UsrCod INT NOT NULL,
UNIQUE INDEX(UsrCod)) ENGINE=MEMORY
SELECT my_usr_cod AS UsrCod
UNION
SELECT FollowedCod AS UsrCod
FROM usr_follow
WHERE FollowerCod=my_usr_cod;
SELECT tml_pubs.PubCod,
tml_pubs.NotCod,
tml_pubs.PublisherCod,
tml_pubs.PubType
FROM tml_pubs,
fol_tmp_me_and_followed
WHERE tml_pubs.PublisherCod=fol_tmp_me_and_followed.UsrCod
AND tml_pubs.NotCod NOT IN
(SELECT NotCod
FROM tml_tmp_timeline)
ORDER BY PubCod DESC
LIMIT 1;
Timeline: getting list of publications
●
Three types of timeline updates
_ ______________________
/ |______________________| Tml_GET_NEW_PUBS
New < |______________________| automatically from time to time
_|______________________| (AJAX)
_|_See_new_activity_(3)_|
/ |______________________| Tml_GET_REC_PUBS
| |______________________| user clicks on action menu
Recent < |______________________| or after editing timeline
| |______________________|
_|______________________|
_|_______See_more_______|
/ |______________________| Tml_GET_OLD_PUBS
| |______________________| user clicks on bottom link
Old < |______________________| (AJAX)
| |______________________|
_|______________________|
Timeline: getting list of publications
tml_pubs
_____
|_____|11
|_____|10
_|_____| 9 <-- RangePubsToGet.Top
Get / |_____| 8
pubs | |_____| 7
from < |_____| 6
this | |_____| 5
range _|_____| 4
|_____| 3 <-- RangePubsToGet.Bottom
|_____| 2
|_____| 1
0
Timeline: getting list of publications
case Tml_GET_REC_PUBS: // Get some limited recent publications
/* First query to get initial timeline shown
==> no notes yet in current timeline table */
RangePubsToGet->Top = 0;
/* _ _____ 0 <-- RangePubsToGet.Top = +infinite
/ |_____| 8
Get | |_____| 7
pubs < |_____| 6
from | |_____| 5
all | |_____| 4
range . |_____| 3
. |_____| 2
. |_____| 1
0 <-- RangePubsToGet.Bottom = -infinite */
RangePubsToGet->Bottom = 0;
Timeline: getting list of publications
case Tml_GET_NEW_PUBS: // Get the publications (without limit)
// newer than last pub. code
/* Via AJAX automatically from time to time */
RangePubsToGet->Top = 0;
/* _ _____ 0 <-- RangePubsToGet.Top = +infinite
Get / |_____|11
these < |_____|10
pubs _|_____| 9
/ |_____| 8 <-- RangePubsToGet.Bottom = last pub. code
Pubs | |_____| 7
already < |_____| 6
shown | |_____| 5
| |_____| 4
. |_____| .
. |_____| .
. |_____| .
*/
RangePubsToGet->Bottom = Tml_DB_GetPubCodFromSession (Tml_Pub_LAST);
Timeline: getting list of publications
case Tml_GET_OLD_PUBS: // Get some limited publications
// older than first pub. code
/* Via AJAX when I click in link to get old publications */
RangePubsToGet->Top = Tml_DB_GetPubCodFromSession (Tml_Pub_FIRST);
/* _____
. |_____| .
. |_____| .
. |_____| .
Pubs | |_____| 8
already < |_____| 7
shown | |_____| 6
| |_____| 5
Get _|_____| 4 <-- RangePubsToGet.Top = first pub. code
pubs / |_____| 3
from < |_____| 2
this _|_____| 1
rage 0 <-- RangePubsToGet.Bottom = -infinite */
RangePubsToGet->Bottom = 0;
Timeline: getting list of publications
●
Restricting publications to range:
SELECT tml_pubs.PubCod,
tml_pubs.NotCod,
tml_pubs.PublisherCod,
tml_pubs.PubType
FROM tml_pubs,
fol_tmp_me_and_followed
WHERE tml_pubs.PublisherCod=fol_tmp_me_and_followed.UsrCod
AND tml_pubs.PubCod>bottom // if type == Tml_GET_REC_PUBS
AND tml_pubs.PubCod<top // updated every iteration
// to last pub. code got
AND tml_pubs.NotCod NOT IN
(SELECT NotCod
FROM tml_tmp_timeline)
ORDER BY PubCod DESC
LIMIT 1;
Timeline: getting list of publications
Timeline->Pubs.Top Pub #0
______ ______ Pub #1
|______|------>|______| ______ Pub #2
|______| -> |______| ______ Pub #3
|______| / |______| ->|______| ______
|______| / |______| / |______| ->|______|
|_Next_|-- |______| / |______| // |______|
more recent |_Next_|-- |______| // |______|
______ |_Next_|--/ |______|
|______|---------------------------------------------- |_NULL_|
older
Timeline->Pubs.Bottom
●
After getting the publications, the result is a chained list:
Timeline: showing publications
_____
/ |_____| just_now_timeline_list (Posts retrieved automatically
| |_____| via AJAX from time to time.
| |_____| They are transferred inmediately
| | to new_timeline_list.)
Hidden < __v__
| |_____| new_timeline_list (Posts retrieved but hidden.
| |_____| When user clicks to view them,
| |_____| the most recent of each note is
 |_____| is transferred
| to visible timeline_list.)
See new activity (0)
__v__
/ |_____| timeline_list (Posts visible on page)
| |_____|
Visible | |_____|
on < |_____|
page | |_____|
| |_____|
 |_____|
^
See more
__|__
/ |_____| old_timeline_list (Posts just retrieved via AJAX
| |_____| when user clicks "see more".
| |_____| They are transferred inmediately
Hidden < |_____| to timeline_list.)
| |_____|
| |_____|
 |_____|
Timeline: showing publications
_____
/ |_____| just_now_timeline_list
| |_____|
| |_____|
| |
Hidden < __v__
| |_____| new_timeline_list
| |_____|
| |_____|
 |_____|
|
See new activity (0)
__v__
/ |_____| timeline_list
| |_____|
Visible | |_____|
on < |_____|
page | |_____|
| |_____|
 |_____|
^
See more
__|__
/ |_____| old_timeline_list
| |_____|
| |_____|
Hidden < |_____|
| |_____|
| |_____|
 |_____|
<ul id="just_now_timeline_list" ...>
</ul>
<ul id="new_timeline_list" ...>
</ul>
<div id="view_new_container" ...
style="display:none;">
<a href="" ...
onclick="moveNewTimelineToTimeline();
return false;">
See new activity
(<span id="view_new_count">
0
</span>)
</a>
</div>
<ul id="timeline_list" ...>
visible timeline
</ul>
<div id="view_old_container" ...>
<a href="" ...
onclick="...
refreshOldTimeline();
return false;">
...
See more
</a>
</div>
<ul id="old_timeline_list" ...>
</ul>
Timeline: showing publications
<head>
...
<script type="text/javascript" ...>
var delayNewTml = Cfg_TIME_TO_REFRESH_TIMELINE; // 2000 ms
function init() {
ActionAJAX = "SWAD_URL";
...
setTimeout('refreshNewTml()',delayNewTL);
...
}
</script>
<script type="text/javascript" ...>
var refreshParamIdSes = "ses=...";
var refreshParamNxtActNewPub = "act=...";
var refreshParamWho = "Who=...";
</script>
...
</head>
<body onload="init();">
...
</body>
●
Automatic refresh via AJAX:
●
every 2 s → 3 s → 4 s → 5 s...
just_now_timeline_list
_____
|_____|
|_____|
|_____|
|
__v__
|_____|
|_____|
|_____|
|_____|
new_timeline_list
Timeline: showing publications
// This function must be called from time to time
var objXMLHttpReqNewTml = false;
function refreshNewTml () {
objXMLHttpReqNewTml = AJAXCreateObject(); // new XMLHttpRequest()
if (objXMLHttpReqNewTml) {
var RefreshParams = refreshParamNxtActNewPub + '&' +
refreshParamIdSes + '&' +
refreshParamWho;
objXMLHttpReqNewTml.onreadystatechange = readNewTimelineData;
objXMLHttpReqNewTml.open('POST',ActionAJAX,true);
objXMLHttpReqNewTml.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');
objXMLHttpReqNewTml.send(RefreshParams);
}
}
●
Automatic refresh via AJAX
●
every 2 s → 3 s → 4 s → 5 s...
just_now_timeline_list
_____
|_____|
|_____|
|_____|
|
__v__
|_____|
|_____|
|_____|
|_____|
new_timeline_list
Timeline: showing publications
function readNewTimelineData () {
if (objXMLHttpReqNewTml.readyState == 4) // Check if data have been received
if (objXMLHttpReqNewTml.status == 200) {
// Access to UL for just now timeline
var justNowTimeline = document.getElementById('just_now_timeline_list');
if (justNowTimeline) {
// Update list of publications in just now timeline
justNowTimeline.innerHTML = objXMLHttpReqNewTml.responseText;
var numNotesJustGot = justNowTimeline.childNodes.length;
if (numNotesJustGot) {// New notes received
// Scripts in timeline got via AJAX are not executed ==> execute them
evalScriptsInElem (justNowTimeline);
// Process maths
MathJax.typeset();
// Move all the LI elements (notes) in UL 'just_now_timeline_list'...
// ...to the top of UL 'new_timeline_list'
var newTimeline = document.getElementById('new_timeline_list');
for (var i=0; i<numNotesJustGot; i++) {
// Move node from just now timeline to new timeline
newTimeline.insertBefore(justNowTimeline.lastChild,newTimeline.firstChild);
newTimeline.firstChild.className += " Tml_NEW_PUB";
}
// Update number of notes in new timeline
var viewNewCount = document.getElementById('view_new_count');
viewNewCount.innerHTML = newTimeline.childNodes.length;
// Unhide message with number of notes if hidden
var viewNewContainer = document.getElementById('view_new_container');
viewNewContainer.style.display = '';
}
}
// Global delay variable is set initially in swad-core
delayNewTml += 1000; // Increase one second on each call
setTimeout('refreshNewTml()',delayNewTml);
}
}
just_now_timeline_list
_____
|_____|
|_____|
|_____|
|
__v__
|_____|
|_____|
|_____|
|_____|
new_timeline_list
Timeline: showing publications
function moveNewTimelineToTimeline () {
// Move the LI elements (notes) in UL 'new_timeline_list'...
// ...to the top of UL 'timeline_list', only if not repeated before
var newTimeline = document.getElementById('new_timeline_list');
var numNewNotes = newTimeline.childNodes.length;
if (numNewNotes) {
var timeline = document.getElementById("timeline_list");
for (var i=1; i<=numNewNotes; i++) {
// Check if the last child (the oldest) in the new timeline...
// ...is the last ocurrence of the note
var mostRecentOcurrenceOfNote = true;
var lastChildIndex = numNewNotes - i;
var noteCode = newTimeline.lastChild.dataset.noteCode;
for (var j=0; j<lastChildIndex; j++)
if (newTimeline.childNodes[j].dataset.noteCode == noteCode) {
mostRecentOcurrenceOfNote = false;
break;
}
// Move or remove node from new timeline
if (mostRecentOcurrenceOfNote) {
// Move node from new timeline to timeline
timeline.insertBefore(newTimeline.lastChild,timeline.firstChild);
timeline.firstChild.className += " Tml_NEW_PUB";
}
else
// Remove last child (because is repeated in more recent pubs)
newTimeline.removeChild(newTimeline.lastChild);
}
}
// Reset number of new publications after moving
var viewNewCount = document.getElementById('view_new_count');
viewNewCount.innerHTML = 0;
// Hide link to view new publications after moving
var viewNewContainer = document.getElementById('view_new_container');
viewNewContainer.style.display = 'none';
}
new_timeline_list
_____
|_____|
|_____|
|_____|
|_____|
|
See new activity (4)
__v__
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
timeline_list
Timeline: showing publications
// This function is called when user clicks in 'See more'
var objXMLHttpReqOldTml = false;
function refreshOldTimeline () {
objXMLHttpReqOldTml = AJAXCreateObject (); // new XMLHttpRequest()
if (objXMLHttpReqOldTml) {
var refreshParams = refreshParamNxtActOldPub + '&' +
refreshParamIdSes;
if (typeof refreshParamUsr !== 'undefined') {
if (refreshParamUsr.length)
refreshParams += '&' + refreshParamUsr;
}
if (typeof refreshParamWho !== 'undefined') {
if (refreshParamWho.length)
refreshParams += '&' + refreshParamWho;
}
objXMLHttpReqOldTml.onreadystatechange = readOldTimelineData;
objXMLHttpReqOldTml.open('POST',actionAJAX,true);
objXMLHttpReqOldTml.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');
objXMLHttpReqOldTml.send(refreshParams);
}
}
●
View old publications: when user clicks "See more..."
timeline_list
_____
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
^
See more
__|__
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
old_timeline_list
Timeline: showing publications
function readOldTimelineData () {
if (objXMLHttpReqOldTml.readyState == 4) // Check if data have been received
if (objXMLHttpReqOldTml.status == 200) {
// Access to UL with the old timeline
var oldTimeline = document.getElementById('old_timeline_list');
if (oldTimeline) {
// Fill list of publications in old timeline
oldTimeline.innerHTML = objXMLHttpReqOldTml.responseText;
var countOldTimeline = oldTimeline.childNodes.length;
if (countOldTimeline) {
// Scripts in timeline got via AJAX are not executed ==> execute them
evalScriptsInElem (oldTimeline);
// Process maths
MathJax.typeset();
// Move all the LI elements in UL 'old_timeline_list'
// to the bottom of UL 'timeline_list'
var timeline = document.getElementById("timeline_list");
for (var i=0; i<countOldTimeline; i++)
timeline.appendChild(oldTimeline.firstChild);
// There may be more publications
// Unhide icon to be hidden on click
document.getElementById('get_old_timeline').style.display = '';
// Hide icon to be shown on click
document.getElementById('getting_old_timeline').style.display = 'none';
}
else // No old publications retrieved, so we have reached the oldest publication
// Hide container with link to get old publications
document.getElementById("view_old_pubs_container").style.display = 'none';
}
}
}
timeline_list
_____
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
^
See more
__|__
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
|_____|
old_timeline_list
Layout: notes
___________________________________________
| | 
| Top message: | > top message
|___________________________________________| /
| _____ | | |  
|| | | Author's name | Date-time | | |
||Auth.| |______________________|___________| | |
||photo| | | | author's |
||_____| | | > name, time |
| | Note | | and content |
| | content | | |
| | | | |
| |__________________________________| / |
| | | | |  |
| | Favs | Shared |Remove| | > note
| |_____________|_____________|______| | |
|________| | | |
| | List | | buttons |
| Comment| of | > and |
| icon | comments | | comments |
|________|__________________________________| | |
| | | |
| Form to write new comment | | |
|__________________________________| / /
Layout: comments
___________________________________________
| _____ | | |  
|| | | Author's name | Date-time | | |
||Auth.| |______________________|___________| | |
||photo| | | | author's |
||_____| | | > name, time |
| | Comment | | and content > comment
| | content | | |
| | | | |
| |__________________________________| / |
| | | |  |
| | Favs |Remove| > buttons |
|________|___________________________|______| / /
Layout: comments
Before clicking "See prev..." --> After clicking "See prev..."
_________________________________ _________________________________
| div con_<id> | | div con_<id> |
| (hidden) | | (visible) |
| _____________________________ | | _____________________________ |
| | v See only the latest | | | | v See only the latest | |
| |_________(contract)__________| | | |_________(contract)__________| |
|_________________________________| |_________________________________|
_________________________________ _________________________________
| div <id> | | div <id> updated |
| which content | | _____________________________ |
| will be updated via AJAX | | | ul com_<id> | |
| (parent of parent of form) | | | _________________________ | |
| | | | | li (comment 1) | | |
| | | | |_________________________| | |
| | | | | ... | | |
| | | | |_________________________| | |
| | | | | li (comment n) | | |
| | --> | | |_________________________| | |
| | | |_____________________________| |
| _____________________________ | | _____________________________ |
| | div exp_<id> | | | | div exp_<id> | |
| | (visible) | | | | (hidden) | |
| | _________________________ | | | | | |
| | | form | | | | | | |
| | | _____________________ | | | | | _____________________ | |
| | | | ^ See prev.comments | | | | | | | ^ See prev.comments | | |
| | | |_______(expand)______| | | | | | |_______(expand)______| | |
| | |_________________________| | | | | | |
| |_____________________________| | | |_____________________________| |
|_________________________________| |_________________________________|
_________________________________ _________________________________
| ul | | ul |
| _________________________ | | _________________________ |
| | li (comment n+1) | | | | li (comment n+1) | |
| |_________________________| | | |_________________________| |
| | ... | | | | ... | |
| |_________________________| | | |_________________________| |
| | li (comment m) | | | | li (comment m) | |
| |_________________________| | | |_________________________| |
|_________________________________| |_________________________________|
Layout: favs & shared
_container_____________________________________________
| _<id>_med_ico |
| |____Clip_____| |
| |
| _container <id>_med_upl_(initially hidden)_________ |
| | _box___________________________________________ | |
| | | ? | | |
| | | Multimedia | | |
| | | | | |
| | | _prefs_container___________________ | | |
| | | | _pref_container_________________ | | | |
| | | | | _______ _______ _______ | | | | |
| | | | | | Image/| |YouTube| | Embed | | | | | |
| | | | | |_video_| |_______| |_______| | | | | |
| | | | |_______________________________| | | | |
| | | |___________________________________| | | |
| | | _file_container____________________________ | | |
| | | | ___________ | | | |
| | | | |_Browse..._| No file selected. | | | |
| | | |___________________________________________| | | |
| | | _URL_container_____________________________ | | |
| | | | _______________________________________ | | | |
| | | | |_Link__________________________________| | | | |
| | | |___________________________________________| | | |
| | | _title_container___________________________ | | |
| | | | _______________________________________ | | | |
| | | | |_Title/attribution_____________________| | | | |
| | | |___________________________________________| | | |
| | |_______________________________________________| | |
| |___________________________________________________| |
|_______________________________________________________|
Layout: favs & shared
___________________________________________________________________________
| div which content will be updated (parent of parent of form) |
| _____________________ _______ _____________________________________ |
| | div (parent of form)| | div | | div for users | |
| | _________________ | | for | | ______ ______ ______ ______ | |
| | | this form | | | num. | | | | | | | | | form | | |
| | | _____________ | | | of | | | user | | user | | user | | to | | |
| | | | fav icon | | | | users | | | 1 | | 2 | | 3 | | show | | |
| | | |_____________| | | | | | | | | | | | | all | | |
| | |_________________| | | | | |______| |______| |______| |______| | |
| |_____________________| |_______| |_____________________________________| |
|___________________________________________________________________________|
typedef enum
{
Tml_Usr_SHOW_FEW_USRS, // Show a few first favers/sharers
Tml_Usr_SHOW_ALL_USRS, // Show all favers/sharers
} Tml_Usr_HowManyUsrs_t;
Future objectives and
tasks
“When they ask me when a program will be ready, I
answer: it depends on how much you work on it.”
Richard Stallman
Future objectives and
tasks
“When they ask me when a program will be ready, I
answer: it depends on how much you work on it.”
Richard Stallman
Future objectives and tasks
●
Objective 1: Incorporate new functionalities in the
platform and improve some of the existing ones for its
integration with gamification, geolocation and EDM
Objective 1 tasks
T1.1 Instructional design + planning T1.5 Improved test exams
T1.2 Monitoring + activity reports T1.6 Scanning homework with the mobile
T1.3 Collaborative edition (wiki) T1.7 Integrated grades
T1.4 Improved schedule + calendar T1.8 Enhanced forums + chat + messages
Future objectives and tasks
●
Objective 2: Integration of gamification based on typical
game elements in the functionalities of the web platform
and the mobile app
Objective 2 tasks
T2.1 ARS integrated (interactive games with remote control)
T2.2 Scores + badges in global and course functionalities
T2.3 Karma in timeline, forums and files
T2.4 Progress bars in user profiles and courses
Future objectives and tasks
●
Objective 3: Integration of indoor geolocation to improve
the location of users in institutional dependencies and
attendance control
Objective 3 tasks
T3.1 Database + location prototype T3.5 Possible improvements
•
Alerts about friends that are close
•
Display location on map
•
QR to check-in
•
Store history for activity reports and
recommendations
T3.2 SWAD API functions
T3.3 Integration in SWADroid
T3.4 Add gamification
Future objectives and tasks
●
Objective 4: Integrate Educational Data Mining techniques
to improve student assessment, identify study tips, and
offer alerts to students and teachers
Objective 4 tasks
T4.1 Study state of the art of EDM (lines of research, articles)
T4.2 Study algorithms + software tools
T4.3 Off-platform experiments (predict + recommend + alert)
T4.4 Select algorithms and integrate them into the platform
Future objectives and tasks
●
Objective 5: Analyze educational changes in motivation and
participation, results, and degree of use and satisfaction
after the improvements
Objective 5 tasks
T5.1 Interviews with users prior to the improvement
T5.2 Acquire reference data prior to improvement
T5.3 Measure indicators after improvement: performance, use, motivation ...
T5.4 Disseminate partial and final results
Conclusions
“We are free, we can be wide open"
Analyse, The Cranberries
Conclusions
“We are free, we can be wide open"
Analyse, The Cranberries
Conclusions
●
We have developed and used an educational platform for
21 years at UGR (Spain)
●
It’s a fast tool that consumes very few computing
resources, making it suitable for low-cost installations
Conclusions
●
It had a great growth between 2005 and 2015
●
In 2015 it was almost used by the entire UGR (≈60K
students)
●
In total, it has been used by 195,000 users at UGR
Conclusions
●
Since 2010 it’s free software, so anyone can install it (and
improve it)
●
Since 2012 it is freely available in the cloud for everyone,
in the portal OpenSWAD.org
●
Of course, you can try it at https://openswad.org/
Conclusions
●
Since 2016 its use at UGR has decreased due to
institutional support to another official platform
●
However, we have continued working on the
improvement of the platform
●
We will continue its upgrade with gamification,
geolocation and data mining, among other features
Thank you!
Antonio Cañas
University of Granada (UGR)
@acanasvargas acanas@ugr.es acanas@openswad.org
https://openswad.org/ @openswad
Thank you!
Antonio Cañas
University of Granada (UGR)
@acanasvargas acanas@ugr.es acanas@openswad.org
https://openswad.org/ @openswad
123
123
Antonio Cañas Vargas

More Related Content

Similar to SWAD Timeline 4:3

Intro to free and open source software for geospatial
Intro to free and open source software for geospatialIntro to free and open source software for geospatial
Intro to free and open source software for geospatial
Lluís Vicens
 

Similar to SWAD Timeline 4:3 (20)

SWAD timeline
SWAD timelineSWAD timeline
SWAD timeline
 
Google Summer of Code with WSO2
Google Summer of Code with WSO2Google Summer of Code with WSO2
Google Summer of Code with WSO2
 
Open Source Portal and Mobile Solutions
Open Source Portal and Mobile SolutionsOpen Source Portal and Mobile Solutions
Open Source Portal and Mobile Solutions
 
SWAD-24-years.pdf
SWAD-24-years.pdfSWAD-24-years.pdf
SWAD-24-years.pdf
 
Online learning platforms
Online learning platformsOnline learning platforms
Online learning platforms
 
QuSandbox+NVIDIA Rapids
QuSandbox+NVIDIA RapidsQuSandbox+NVIDIA Rapids
QuSandbox+NVIDIA Rapids
 
Intro to free and open source software for geospatial
Intro to free and open source software for geospatialIntro to free and open source software for geospatial
Intro to free and open source software for geospatial
 
Dashboards voor learning analytics
Dashboards voor learning analyticsDashboards voor learning analytics
Dashboards voor learning analytics
 
Cooperation Menu for Universities and Researchers in Latvia | Accenture
Cooperation Menu for Universities and Researchers in Latvia | AccentureCooperation Menu for Universities and Researchers in Latvia | Accenture
Cooperation Menu for Universities and Researchers in Latvia | Accenture
 
DSC Aswan University info session
DSC Aswan University info sessionDSC Aswan University info session
DSC Aswan University info session
 
Will Postgres Live Forever?
Will Postgres Live Forever?Will Postgres Live Forever?
Will Postgres Live Forever?
 
JCP & The Future of Java
JCP & The Future of JavaJCP & The Future of Java
JCP & The Future of Java
 
Mark Hughes Annual Seminar Presentation on Open Source
Mark Hughes Annual Seminar Presentation on Open Source Mark Hughes Annual Seminar Presentation on Open Source
Mark Hughes Annual Seminar Presentation on Open Source
 
Top 10 Big Data Technologies | Edureka
Top 10 Big Data Technologies | EdurekaTop 10 Big Data Technologies | Edureka
Top 10 Big Data Technologies | Edureka
 
Software Sustainability in e-Research: Dying for a Change
Software Sustainability in e-Research: Dying for a ChangeSoftware Sustainability in e-Research: Dying for a Change
Software Sustainability in e-Research: Dying for a Change
 
GDSC USeP - Infosession 2023.pptx
GDSC USeP - Infosession 2023.pptxGDSC USeP - Infosession 2023.pptx
GDSC USeP - Infosession 2023.pptx
 
Grand Challenges Learning Analytics
Grand Challenges Learning AnalyticsGrand Challenges Learning Analytics
Grand Challenges Learning Analytics
 
DSC GCOE, Nagpur intro session
DSC GCOE, Nagpur intro sessionDSC GCOE, Nagpur intro session
DSC GCOE, Nagpur intro session
 
Google summer of code with drupal
Google summer of code with drupalGoogle summer of code with drupal
Google summer of code with drupal
 
2017 Q2 uPortal Open Source Support Briefing
2017 Q2 uPortal Open Source Support Briefing2017 Q2 uPortal Open Source Support Briefing
2017 Q2 uPortal Open Source Support Briefing
 

Recently uploaded

%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 

Recently uploaded (20)

WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 

SWAD Timeline 4:3

  • 1. SWAD, an Open Learning Management System Including timeline implementation Antonio Cañas University of Granada (UGR) @acanasvargas acanas@ugr.es acanas@openswad.org https://openswad.org/ @openswad SWAD, an Open Learning Management System Including timeline implementation Antonio Cañas University of Granada (UGR) @acanasvargas acanas@ugr.es acanas@openswad.org https://openswad.org/ @openswad 1 1 Antonio Cañas et al. November 22 2021, Granada, Spain November 22 2021, Granada, Spain
  • 2. Contents ● History and summary of features ● Implementation ● Free software release ● swad.ugr.es figures ● openswad.org ● Future objectives and tasks ● Conclusions
  • 3. History and summary of features “The dream of yesterday is the hope of today and the reality of tomorrow” . Robert H. Goddard History and summary of features “The dream of yesterday is the hope of today and the reality of tomorrow” . Robert H. Goddard
  • 4. LMS in 2021: a very broad offer ● Today: hundreds of LMS ● proprietary / free software ● expensive / free of charge ● installable on the client's servers / accessible in the cloud
  • 5. LMS in 2021: a very broad offer 308
  • 6. LMS in 2021: a very broad offer 619
  • 7. ...but in 1999 there were not so many available, and we started to develop our own system: Sistema Web de Apoyo a la Docencia (Web System for Teaching Support) ⬇ Social Workspace At a Distance https://swad.ugr.es/ https://openswad.org/ A web platform to manage courses, students and teachers, with functions to support teaching and learning. What is SWAD?
  • 8. This is how it looks, although some parts of its appearance, such as colors or icons, are customizable What is SWAD?
  • 9. Features Free software · 9 languages · Responsive design · Android app Face-to-face or blended learning Hierarchical organization: System · Countries · Institutions (universities, companies) · Centers (faculties, schools) · Degrees · Courses · Group types · Groups 10 available roles: Unknown · Guest · User · Student · Non- editing teacher · Teacher · Degree admin · Center admin · Institution admin · System admin
  • 10. Functionality Social network · Calendar · Notifications · Course information · Syllabus · Documents · Shared files · Portfolio · Grades · Assignments · Projects · Exam announcements · Quizzes · Exams · Games · Surveys · Groups · Lists of students and teachers · Attendance control using QR codes · Forums · Notices · Messaging system · Statistics · Agenda · Preferences All features in https://github.com/acanas/swad-core/wiki/UserGuide.en
  • 11. Dpt.ATC: 1999-2003 1º TIP: 2003-2004 2º TIP: 2005-2006 3º TIP: 2006-2008 V.L.Center:2008-2016 Free Software: 2010... UNA.py: 2012-2014 OpenSWAD: 2012… Dpt.ATC: 2016... 21 years of use and development openswad.org 2012... ugr.es CEVUG 2008-2016 ugr.es TIPs 2003-2008 ugr.es ATC 1999-2003 una.py 2012-2015 ugr.es ATC 2016...
  • 12. Free software release “You're frozen When your heart's not open” Frozen, Madonna Free software release “You're frozen When your heart's not open” Frozen, Madonna
  • 13. First release as free software January 21, 2010 Free software office of the University of Granada
  • 14. Steps to release the core 1. Code (names, comments) in English (100%) 2. Code independent from the UGR (100%) 3. Translation to 9 languages (90%) 4. Add AGPL headers to files (100%) 5. Publish the source code (100%) https://openswad.org/source/ 6. Publish the installation procedure (100%) https://openswad.org/install/ 7. Use git version control system (100%) 8. Upload to GitHub (100%) https://github.com/acanas/swad-core 9. Desirable: automate installation (20%)
  • 15. Why do we create free software? ● Because it facilitates collaborative development Fourth Hackathon of free software projects of the UGR, 2012. Photo: A. Cañas
  • 16. Why do we create free software? ● Because it encourages better programming @psicobyte_ explains the benefits of free software. Photo: A. Cañas
  • 17. Why do we create free software? ● Because it improves the code quality Hackathon of SWADroid and SWAD, 2013. Photo: A. Cañas
  • 18. Why do we create free software? ● Because it provides freedom and security to users https://www.gnu.org/philosophy/
  • 19. How much work is behind? swad-core SWADroid Affero GPL v3 license https://github.com/acanas/swad-core GPL v3 license https://github.com/Amab/SWADroid 361,650 C code lines 144 MySQL tables 60,744 Java code lines 17K downloads 94 person-years estimated effort* 14 person-years estimated effort* $5,196,470 estimated cost* $794,070 estimated cost* Other modules and more info: https://openswad.org/source * According to the COCOMO model in Open Hub
  • 20. swad.ugr.es figures “What goes up, must come down” What goes up, The Alan Parsons Project swad.ugr.es figures “What goes up, must come down” What goes up, The Alan Parsons Project
  • 21. 482 million clicks (page views) 386 million (80%) students 26 million (5%) teachers 69 million (14%) others 1 million (<1%) admin. SWAD-UGR - Jan 2005 Nov → 2021
  • 22. 198,402 users have used the platform 173,814 (88%) as students 3913 (2%) as teachers 35,677 (18%) as guests 133 (<1%) as admin. SWAD-UGR - Jan 2005 Nov → 2021
  • 25. ...from 1089institutions ugr 114,774 (74%) from UGR 11,186 (3%) from other institutions 28,776 (22%) unknown 531 degrees 7646 courses SWAD-UGR - Nov 2021
  • 26. 822,749 (1.8 TB) files 46,127 test questions 1399 forums 24 million times answered 66,520 posts SWAD-UGR - Nov 2021
  • 30. Real users / academic year (swad.ugr.es)
  • 31. Page views / week (swad.ugr.es)
  • 32. Users / week (swad.ugr.es)
  • 33. Keys to success at the UGR ● #1: Platform open to the entire University since 2004 I Meeting of SWAD Users
  • 34. Keys to success at the UGR ● #2: Teacher training
  • 35. Keys to success at the UGR ● #3: User support: thousands of queries answered Thank you for your help and efficiency... and for having designed a computer invention that really works, which reconciles me with the new technologies...
  • 36. ● #4: Developed according to the users’ requests Keys to success at the UGR A user wants the platform to congratulate him on his birthday... Days later a new feature congratulates users for their birthdays.
  • 37. Keys to success at the UGR ● #5: Strengths of the tool ● Functionality and usability ● Simplicity ● It has what most teachers asked ● Reliability and safety ● It consumes few resources ● It works 24 hours, fast and almost without failures
  • 38. openswad.org “A planet is the cradle of mind, but one cannot live in a cradle forever.” Konstantin Tsiolkovski (russian physicist) openswad.org “A planet is the cradle of mind, but one cannot live in a cradle forever.” Konstantin Tsiolkovski (russian physicist)
  • 39. SWAD outside the UGR after release ● Little diffusion ● Difficult to reach the target audience (need for advertising) ● Absence of simple installation ● Many competitors ● Many LMS, some of them very widespread ● Released as free software too late (2010) ● A lot of work, small team ● Conclusion ● Very few (two or three) installations
  • 40. The OpenSWAD.org project ● OpenSWAD.org is an installation in the cloud of the SWAD educational platform, offered free of charge for any country by the OpenSWAD Association (non-profit organization, independent of the UGR) ● OpenSWAD.org is available since 2012, but it did not start growing until 2015, when we decided to carry out advertising campaigns
  • 41. Why “Open”? ● Free software (so open source) ● Open and free for everyone ● Open design and interaction ● You can access many features (hierarchy, courses, teachers, statistics) even if you are not logged in ● Open content allowed ● Upload, mark as public and choose license ● Anyone could access, even without log in
  • 42. Steps for internationalization 1. Code independent from the institution (100%) 2. Translation to 9 languages (90%) 3. ISO 8601 format for date-times (100%) 4. Dates-hours independent of location (100%) 5. Calendars independent of location (100%) 6. Weeks starting on Monday or Sunday (100%) 7. Floating point / comma format (10%)
  • 43. Advertising: conversion funnel 2,600,000 ad impressions on Twitter and Facebook 2,600,000 ad impressions on Twitter and Facebook 2600 filled in their data (50%) 2600 filled in their data (50%) 260 created center, degree, course (10%) 260 created center, degree, course (10%) 130,000 clicked link (5%) 130,000 clicked link (5%) 5200 created account ( 5200 created account (4% 4%) ) 130 enrolled in course (50%) 130 enrolled in course (50%) 65 created course content (50%) 65 created course content (50%) 13 used with students (20%, 5 per million) 13 used with students (20%, 5 per million) Example: Feb. 2015 March 2016 →
  • 44. Cost of advertising (2015 2017) → Cost Dates Days Cost/day Impressions Clicks Cost/click Twitter 4650.29€ Feb 12, 2015 Sep 25, 2017 956 4.86 € 14,042,284 50,119 €0.108 Facebook 2400.84€ Sep 26, 2015 Sep 25, 2017 730 3.29 € 12,858,591 192,833 €0.012 AdWords 1255.93€ Feb 16, 2017 Sep 25, 2017 221 5.68 € 392,298 15,046 €0.083 Total 8307.06€ Feb 12, 2015 Sep 25, 2017 956 8.69 € 27,293,173 257,998 €0.032 Courses Teachers Students Total users Courses or users with real use 528 385 1657 18 411 Cost per course or user €15,73 €21,58 €5,01 €0,45
  • 45. Conversion comparison (2017) Cost Dates Days Impresiones Clicks Page views Users New accounts New courses Twitter €66.20 Sep 6 - Sep 24, 2017 7 €9.46 / day 271,072 €0.00024 / impression 734 €0.09 / click 14 632 €0.0045 / page view 342 €0.19 / user 186 €0.36 / new account 10 €6.62 / new course Facebook €109.66 Sep 7 - Sep 25, 2017 7 €15.66 / day 148,206 €0.00074 / impression 3780 €0.03 / click 33 087 €0.0033 / page view 274 €0.40 / user 114 €0.96 / new account 12 €9.14 / new course AdWords €65.83 Sep 5 - Sep 23, 2017 7 €9.40 / day 13,210 €0.00498 / impression 808 €0.08 / click 11 169 €0.0060 / page view 243 €0.27 / user 94 €0.70 / new account 7 €9.40 / new course Total €241.69 Sep 5 - Sep 25, 2017 21 €11.51 / day 432,488 €0.00056 / impression 5322 €0.05 / click 58 888 €0.0041 / page view 859 €0.28 / user 394 €0.61 / new account 29 €8.33 / new course
  • 49. Users / country (OpenSWAD) First countries in OpenSWAD according to number of users First countries in OpenSWAD according to number of users 34,440 users from 152 countries
  • 50. Users / country (OpenSWAD) ● Even a report about OpenSWAD has been broadcast on a Latin American TV channel OpenSWAD in Atomun, Telesur TV (Venezuela), July 2017
  • 51. Users / institution (OpenSWAD) Users from 2924 institutions
  • 52. Users / month 2014 2021 (OpenSWAD) → Advertisements
  • 53. Teachers / month 2014 2021 (OpenSWAD) → Advertisements
  • 54. Students / month 2014 2021 (OpenSWAD) → Advertisements
  • 55. Implementation “Every step that you take Could be your biggest mistake It could bend or it could break That's the risk that you take” What If, Coldplay Implementation “Every step that you take Could be your biggest mistake It could bend or it could break That's the risk that you take” What If, Coldplay
  • 56. The core ● Written from scratch in C (compiled, not interpreted) ✔Advantages: ● + speed ● - memory ● Functional even in a Raspberry Pi ● + stability of source code over time ✘Disadvantages: ● absence of specialized library functions for the web
  • 57. Former servers at the UGR 2nd: 2004-2006 Pentium 4 HT RAM 2 GiB 2 HD 160 GB Fedora 3 3rd: 2007-2008 Core 2 Duo RAM 4 GiB 2 HD 500 GB Fedora 6 4th: 2009-2010 Core 2 Quad RAM 4 GiB 2 HD 146 GB 2 HD 1 TB Fedora 10 5th: 2011-2016 2 Xeon Quad RAM 24 GiB 4 HD 146 GB 4 HD 500 GB CentOS 5.7 1st: 1999-2003 Shared server
  • 58. Current server at the UGR (6th: 2016...) ● HP Proliant DL160 G9, 2 Xeon with 6 cores, RAM 32 GiB 4 HD 146 GB SAS 15000 rpm RAID 1+0 (292 GB) SO CentOS 7.2 MySQL database 4 HD 1 TB SAS 7200 rpm RAID 5 (3 TB) Web files ( /var/www )
  • 59. Plugins ● It is possible to develop add-ons (plugins) that run on: ● other servers ● mobile devices. Example: SWADroid ● The plugins interact with the swad core through an API: https://openswad.org/api/
  • 60. Photographs of users ● Our own automatic system for detecting faces and improving the quality of photos, trained with 90K photos
  • 61. Up to 400K times per day Up to 2000 times / minute (30 times / second) Log “click” logged access HTML server database swad-core
  • 62. 144 database tables. The largest is the one used to store the access log. Database
  • 63. Log table ● It allows analyzing a lot of information: ● By role ● By user ● By action performed ● By qualification ● By subject ● By dates ● ... UGR: 482 million registered hits since 2005
  • 64. Log table Pages per minute (averaged during an academic year) teachers students
  • 65. Log table Matches of the Soccer World Cup 2010 You can even see the rest in the match
  • 66. Log table Peak: students choosing groups Page views per minute
  • 67. Log table ● What if we convert every click into a sound? ● At 1 am: http://swad.ugr.es/stat/clicks/clicks_1am.wav ● At 1 pm: http://swad.ugr.es/stat/clicks/clicks_1pm.wav ● Peak (students choosing groups): http://swad.ugr.es/stat/clicks/clicks_grupos.wav
  • 68. Who has developed it? ● Recent programmers: ● Antonio Cañas Vargas (swad-core, servers, management, courses) ● Daniel J. Calandria Hernández (photo processing, chat) ● Juan Miguel Boyero Corral (SWADroid) ● Adrián Lara Roldán (iSWAD) ● Jesús Mesa González (photo processing) ● Sergio Díaz Rueda (SWADroid) (green = free software)
  • 69. Who has developed it? ● Former programmers (I): ● Jesús Álvarez Martín (photo processing) ● Alberto E. Rodrigo Gámiz (photo processing) ● Ana Belén Cara Carmona (chat & whiteboard) ● Carlos Moreno Muñoz (chat & whiteboard)
  • 70. Who has developed it? ● Former programmers (II): ● Antonio Manuel Aguilera Malagón (SWADroid) ● Helena Rodríguez Gijón (SWADroid) ● José Antonio Guerrero Avilés (SWADroid) ● Alejandro Alcalde Barros (SWADroid) ● Rubén Martín Hidalgo (SWADroid) ● Miguel Ángel Cerrailo Valle (Triswados, app Android) ● Raúl Álvarez Hinojosa (iSWAD)
  • 71. Who has developed it? ● Programmers of modules that were not used: ● Andrés Ramón Masegosa Aredondo (photo processing) ● Raúl Jiménez Benítez (chat) ● María Beatriz Medina Yáñez (whiteboard) ● Raquel Cazalilla Sáez (chat & whiteboard) ● Emiliano Luis Rincón Vallejos (rich text editor) ● Diego Montesinos Hervás (iSWAD) ● Lucas Ortiz Velasco (SWADMyPage) ● David Medina Godoy (SWADE, rich text editor) ● Marta Muñoz López (SWAD2Moodle)
  • 72. Who has developed it? ● Translators: ● Antonio Cañas Vargas (CA,DE,EN,ES,FR,GN,IT,PL,PT) ● Joan Lluís Díaz Rodríguez (CA) ● Rafael Barranco Droege (DE) ● Giuseppe Antonio Pagin, Antonella Grande, Francisco Manuel Herrero Pérez, Nicola Comunale Rizzo (IT) ● Wojtek Kieca, Tomasz Olechowski, Mateusz Stanko (PL)
  • 73. Who has developed it? ● Contributors (I): ● Javier Fernández Baldomero (forums, papers) ● Antonio F. Díaz García (servers) ● Eva Martínez Ortigosa (administration, papers) ● Francisco Illeras García (servers) ● Alberto Prieto Espinosa (papers) ● Beatriz Prieto Campos (papers) ● Begoña del Pino Prieto (papers) ● Mancia Anguita López (papers) ● Eduardo Ros Vidal (papers)
  • 74. Who has developed it? ● Contributors (II): ● Francisco A. Ocaña Lara (FAQ, papers) ● Adrián Gómez Anaya (WikiSwad) ● Paloma Marín Arraiza (video tutorials) ● technicians and scholars from the Virtual Learning Center ● ~120 degree administrators ● ...and many more
  • 75. Timeline “You think you know when you learn, are more sure when you can write, even more when you can teach, but certain when you can program.” Alan Perlis Timeline “You think you know when you learn, are more sure when you can write, even more when you can teach, but certain when you can program.” Alan Perlis
  • 76. Timeline, notes, publications ● Timeline: set of publications ● from a user ● global ● Only me ● Followed users ● All users typedef enum { Tml_Usr_TIMELINE_USR, Tml_Usr_TIMELINE_GBL, } Tml_Usr_UsrOrGbl_t; typedef enum { Usr_WHO_UNKNOWN, Usr_WHO_ME, Usr_WHO_SELECTED, // Not applicable to timeline Usr_WHO_FOLLOWED, Usr_WHO_ALL, } Usr_Who_t;
  • 77. Timeline, notes, publications ● Publication: · original note (24805, 78% of 31845) · shared note ( 1282, 4% of 31845) · comment to a note ( 5758, 18% of 31845) struct Tml_Pub_Publication { long PubCod; // Publication code long NotCod; // Note code long PublisherCod; // Sharer or writer of the publication Tml_Pub_Type_t Type; // Original note, shared note, comment struct Tml_Pub_Publication *Next; // Used for chained list }; *swad.ugr.es, nov 2021
  • 78. Timeline, notes, publications ● Note: timeline post ( 4163, 17% of 24805) public file ( 66, <1% of 24805) call for exam ( 2727, 11% of 24805) notice (17567, 71% of 24805) forum post ( 282, 1% of 24805) *swad.ugr.es, nov 2021
  • 79. Timeline, notes, publications struct Tml_Not_Note { long NotCod; // Unique code/identifier for each note Tml_Not_Type_t Type; // Timeline post, public file, // call for exam, notice, forum post... long UsrCod; // Publisher long HieCod; // Hierarchy code // (institution/center/degree/course) long Cod; // Code of file, forum post, // notice, timeline post... bool Unavailable; // File, forum post, notice,... // unavailable (removed) time_t DateTimeUTC; // Date-time of publication in UTC time unsigned NumShared; // Number of times (users) // this note has been shared unsigned NumFavs; // Number of times (users) // this note has been favourited };
  • 80. Timeline, notes, publications __________________ |@author | | Note | |__________________| |@author | | Comment 1 | |______________| |@author | | Comment 2 | |______________| | | | ... | |______________| |@author | | Comment n | |______________| ● A note can have comments attached to it:
  • 81. Timeline, notes, publications _tml_pubs______ _tml_comments | | | | | Publication p |---------->| Comment c |-----+ | (comment) | | (to note 2) | | |_______________| |_____________| | | | | | | · ... · · ... · | · ... · · ... · | |_______________| |_____________| | | | | | | |Publication i+4|---------->| Comment 1 |---+ | | (comment) | | (to note n) | | | |_______________| |_____________| | | | | (4855) | | |Publication i+3|-- | | |(original note)| | | |_______________| _tml_notes_____ | | _cfe_exams_____ | | | | | | | | |Publication i+2|-- ---->| Note n |<-+ | | Call for exam | (5581) |(original note)| |(exam announc.)|-(2622)->|_______________| |_______________| |_______________| 11% __brw_files____ | | | | | | | |Publication i+1|-- ---->| Note n-1 |-(64)--->| Public file | (1497132) |(original note)| | (public file) | <1% |_______________| |_______________| |_______________| | _not_notices___ | | | | | | | | Publication i |-- ---->| Note n-2 |-(17078)>| Notice | (14984) |(original note)| | (notice) | 72% |_______________| |_______________| |_______________| | __tml_posts____ | | | | | | | · ... · ---->| Note n-3 |-(3533)->| Post s | · ... · | (tl. post) | 15% | | |_______________| |_______________| | |_______________| | | | | | | | | Publication 3 | · ... · | · ... · (3533) | (shared note) |--- · ... · | · ... · |_______________| |_______________| | |_______________| | | | | | | | | Publication 2 | ---->| Note 2 |<---+ | Post 1 | |(original note)|--------->| (tl. post) |-------->| | |_______________| |_______________| |_______________| | | | | _for_posts_____ | Publication 1 |--------->| Note 1 | | | |(original note)| | (forum post) |-(276)-->| Forum post | (66226) |_______________| |_______________| 1% |_______________| (29435) (23573) timeline posts public files calls for exams notices forum posts notes comments publications
  • 82. 144 database tables. The largest is the one used to store the access log. Database
  • 83. Database mysql> SHOW TABLES LIKE 'tml_%'; +------------------------+ | Tables_in_swad (tml_%) | +------------------------+ | tml_comments | | tml_comments_fav | | tml_notes | | tml_notes_fav | | tml_posts | | tml_pubs | | tml_timelines | +------------------------+ 7 rows in set (0.00 sec)
  • 84. Database: publications mysql> DESCRIBE tml_pubs; +--------------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+----------+------+-----+---------+----------------+ | PubCod | bigint | NO | PRI | NULL | auto_increment | | NotCod | bigint | NO | MUL | NULL | | | PublisherCod | int | NO | MUL | NULL | | | PubType | tinyint | NO | MUL | NULL | | | TimePublish | datetime | NO | MUL | NULL | | +--------------+----------+------+-----+---------+----------------+
  • 85. Database: notes mysql> DESCRIBE tml_notes; +-------------+---------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+---------------+------+-----+---------+----------------+ | NotCod | bigint | NO | PRI | NULL | auto_increment | | NoteType | tinyint | NO | MUL | NULL | | | Cod | int | NO | | -1 | | | UsrCod | int | NO | MUL | NULL | | | HieCod | int | NO | | -1 | | | Unavailable | enum('N','Y') | NO | | N | | | TimeNote | datetime | NO | MUL | NULL | | +-------------+---------------+------+-----+---------+----------------+ mysql> DESCRIBE tml_notes_fav; +---------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+----------+------+-----+---------+----------------+ | FavCod | bigint | NO | PRI | NULL | auto_increment | | NotCod | bigint | NO | MUL | NULL | | | UsrCod | int | NO | MUL | NULL | | | TimeFav | datetime | NO | | NULL | | +---------+----------+------+-----+---------+----------------+
  • 86. Database: comments mysql> DESCRIBE tml_comments; +--------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+----------+------+-----+---------+-------+ | PubCod | bigint | NO | PRI | NULL | | | Txt | longtext | NO | MUL | NULL | | | MedCod | int | NO | MUL | -1 | | +--------+----------+------+-----+---------+-------+ mysql> DESCRIBE tml_comments_fav; +---------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+----------+------+-----+---------+----------------+ | FavCod | bigint | NO | PRI | NULL | auto_increment | | PubCod | bigint | NO | MUL | NULL | | | UsrCod | int | NO | MUL | NULL | | | TimeFav | datetime | NO | | NULL | | +---------+----------+------+-----+---------+----------------+
  • 87. Database: posts mysql> DESCRIBE tml_posts; +--------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------+----------+------+-----+---------+----------------+ | PstCod | int | NO | PRI | NULL | auto_increment | | Txt | longtext | NO | MUL | NULL | | | MedCod | int | NO | MUL | -1 | | +--------+----------+------+-----+---------+----------------+ mysql> DESCRIBE cfe_exams; +-------------+---------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+---------------+------+-----+---------+----------------+ | ExaCod | int | NO | PRI | NULL | auto_increment | | ... | ... | ... | ... | ... | ... | mysql> DESCRIBE brw_files; +-----------------+---------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------------+---------------+------+-----+---------+----------------+ | FilCod | int | NO | PRI | NULL | auto_increment | | ... | ... | ... | ... | ... | ... | mysql> DESCRIBE not_notices; +-----------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+----------+------+-----+---------+----------------+ | NotCod | int | NO | PRI | NULL | auto_increment | | ... | ... | ... | ... | ... | ... | mysql> DESCRIBE for_posts; +-----------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+----------+------+-----+---------+----------------+ | PstCod | int | NO | PRI | NULL | auto_increment | | ... | ... | ... | ... | ... | ... |
  • 88. Database: timelines mysql> DESCRIBE tml_timelines; +-----------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+----------+------+-----+---------+-------+ | SessionId | char(43) | NO | PRI | NULL | | | NotCod | bigint | NO | PRI | NULL | | +-----------+----------+------+-----+---------+-------+ mysql> DESCRIBE tml_tmp_timeline; +--------+--------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+--------+------+-----+---------+-------+ | NotCod | bigint | NO | PRI | NULL | NULL | +--------+--------+------+-----+---------+-------+
  • 89. Timeline: getting list of publications ● Our algorithm: ● Select publications one by one in a loop ● In each iteration: ● Get the most recent publication (original, shared or comment) checking that its note is not already retrieved ● After getting a publication, save its note code to not get it again. SELECT PubCod FROM tml_pubs WHERE NotCod NOT IN (SELECT NotCod FROM tml_tmp_timeline) ORDER BY PubCod DESC LIMIT 1;
  • 90. Timeline: getting list of publications ● Slower alternative (may need seconds for large tables): ● Get the maximum PubCod, i.e more recent publication (original, shared or commment), of every set of publications corresponding to the same note: SELECT MAX(PubCod) AS NewestPubCod FROM tml_pubs GROUP BY NotCod ORDER BY NewestPubCod DESC LIMIT 10;
  • 91. Timeline: getting list of publications ● Restricting publications to mine and those I follow: CREATE TEMPORARY TABLE fol_tmp_me_and_followed (UsrCod INT NOT NULL, UNIQUE INDEX(UsrCod)) ENGINE=MEMORY SELECT my_usr_cod AS UsrCod UNION SELECT FollowedCod AS UsrCod FROM usr_follow WHERE FollowerCod=my_usr_cod; SELECT tml_pubs.PubCod, tml_pubs.NotCod, tml_pubs.PublisherCod, tml_pubs.PubType FROM tml_pubs, fol_tmp_me_and_followed WHERE tml_pubs.PublisherCod=fol_tmp_me_and_followed.UsrCod AND tml_pubs.NotCod NOT IN (SELECT NotCod FROM tml_tmp_timeline) ORDER BY PubCod DESC LIMIT 1;
  • 92. Timeline: getting list of publications ● Three types of timeline updates _ ______________________ / |______________________| Tml_GET_NEW_PUBS New < |______________________| automatically from time to time _|______________________| (AJAX) _|_See_new_activity_(3)_| / |______________________| Tml_GET_REC_PUBS | |______________________| user clicks on action menu Recent < |______________________| or after editing timeline | |______________________| _|______________________| _|_______See_more_______| / |______________________| Tml_GET_OLD_PUBS | |______________________| user clicks on bottom link Old < |______________________| (AJAX) | |______________________| _|______________________|
  • 93. Timeline: getting list of publications tml_pubs _____ |_____|11 |_____|10 _|_____| 9 <-- RangePubsToGet.Top Get / |_____| 8 pubs | |_____| 7 from < |_____| 6 this | |_____| 5 range _|_____| 4 |_____| 3 <-- RangePubsToGet.Bottom |_____| 2 |_____| 1 0
  • 94. Timeline: getting list of publications case Tml_GET_REC_PUBS: // Get some limited recent publications /* First query to get initial timeline shown ==> no notes yet in current timeline table */ RangePubsToGet->Top = 0; /* _ _____ 0 <-- RangePubsToGet.Top = +infinite / |_____| 8 Get | |_____| 7 pubs < |_____| 6 from | |_____| 5 all | |_____| 4 range . |_____| 3 . |_____| 2 . |_____| 1 0 <-- RangePubsToGet.Bottom = -infinite */ RangePubsToGet->Bottom = 0;
  • 95. Timeline: getting list of publications case Tml_GET_NEW_PUBS: // Get the publications (without limit) // newer than last pub. code /* Via AJAX automatically from time to time */ RangePubsToGet->Top = 0; /* _ _____ 0 <-- RangePubsToGet.Top = +infinite Get / |_____|11 these < |_____|10 pubs _|_____| 9 / |_____| 8 <-- RangePubsToGet.Bottom = last pub. code Pubs | |_____| 7 already < |_____| 6 shown | |_____| 5 | |_____| 4 . |_____| . . |_____| . . |_____| . */ RangePubsToGet->Bottom = Tml_DB_GetPubCodFromSession (Tml_Pub_LAST);
  • 96. Timeline: getting list of publications case Tml_GET_OLD_PUBS: // Get some limited publications // older than first pub. code /* Via AJAX when I click in link to get old publications */ RangePubsToGet->Top = Tml_DB_GetPubCodFromSession (Tml_Pub_FIRST); /* _____ . |_____| . . |_____| . . |_____| . Pubs | |_____| 8 already < |_____| 7 shown | |_____| 6 | |_____| 5 Get _|_____| 4 <-- RangePubsToGet.Top = first pub. code pubs / |_____| 3 from < |_____| 2 this _|_____| 1 rage 0 <-- RangePubsToGet.Bottom = -infinite */ RangePubsToGet->Bottom = 0;
  • 97. Timeline: getting list of publications ● Restricting publications to range: SELECT tml_pubs.PubCod, tml_pubs.NotCod, tml_pubs.PublisherCod, tml_pubs.PubType FROM tml_pubs, fol_tmp_me_and_followed WHERE tml_pubs.PublisherCod=fol_tmp_me_and_followed.UsrCod AND tml_pubs.PubCod>bottom // if type == Tml_GET_REC_PUBS AND tml_pubs.PubCod<top // updated every iteration // to last pub. code got AND tml_pubs.NotCod NOT IN (SELECT NotCod FROM tml_tmp_timeline) ORDER BY PubCod DESC LIMIT 1;
  • 98. Timeline: getting list of publications Timeline->Pubs.Top Pub #0 ______ ______ Pub #1 |______|------>|______| ______ Pub #2 |______| -> |______| ______ Pub #3 |______| / |______| ->|______| ______ |______| / |______| / |______| ->|______| |_Next_|-- |______| / |______| // |______| more recent |_Next_|-- |______| // |______| ______ |_Next_|--/ |______| |______|---------------------------------------------- |_NULL_| older Timeline->Pubs.Bottom ● After getting the publications, the result is a chained list:
  • 99. Timeline: showing publications _____ / |_____| just_now_timeline_list (Posts retrieved automatically | |_____| via AJAX from time to time. | |_____| They are transferred inmediately | | to new_timeline_list.) Hidden < __v__ | |_____| new_timeline_list (Posts retrieved but hidden. | |_____| When user clicks to view them, | |_____| the most recent of each note is |_____| is transferred | to visible timeline_list.) See new activity (0) __v__ / |_____| timeline_list (Posts visible on page) | |_____| Visible | |_____| on < |_____| page | |_____| | |_____| |_____| ^ See more __|__ / |_____| old_timeline_list (Posts just retrieved via AJAX | |_____| when user clicks "see more". | |_____| They are transferred inmediately Hidden < |_____| to timeline_list.) | |_____| | |_____| |_____|
  • 100. Timeline: showing publications _____ / |_____| just_now_timeline_list | |_____| | |_____| | | Hidden < __v__ | |_____| new_timeline_list | |_____| | |_____| |_____| | See new activity (0) __v__ / |_____| timeline_list | |_____| Visible | |_____| on < |_____| page | |_____| | |_____| |_____| ^ See more __|__ / |_____| old_timeline_list | |_____| | |_____| Hidden < |_____| | |_____| | |_____| |_____| <ul id="just_now_timeline_list" ...> </ul> <ul id="new_timeline_list" ...> </ul> <div id="view_new_container" ... style="display:none;"> <a href="" ... onclick="moveNewTimelineToTimeline(); return false;"> See new activity (<span id="view_new_count"> 0 </span>) </a> </div> <ul id="timeline_list" ...> visible timeline </ul> <div id="view_old_container" ...> <a href="" ... onclick="... refreshOldTimeline(); return false;"> ... See more </a> </div> <ul id="old_timeline_list" ...> </ul>
  • 101. Timeline: showing publications <head> ... <script type="text/javascript" ...> var delayNewTml = Cfg_TIME_TO_REFRESH_TIMELINE; // 2000 ms function init() { ActionAJAX = "SWAD_URL"; ... setTimeout('refreshNewTml()',delayNewTL); ... } </script> <script type="text/javascript" ...> var refreshParamIdSes = "ses=..."; var refreshParamNxtActNewPub = "act=..."; var refreshParamWho = "Who=..."; </script> ... </head> <body onload="init();"> ... </body> ● Automatic refresh via AJAX: ● every 2 s → 3 s → 4 s → 5 s... just_now_timeline_list _____ |_____| |_____| |_____| | __v__ |_____| |_____| |_____| |_____| new_timeline_list
  • 102. Timeline: showing publications // This function must be called from time to time var objXMLHttpReqNewTml = false; function refreshNewTml () { objXMLHttpReqNewTml = AJAXCreateObject(); // new XMLHttpRequest() if (objXMLHttpReqNewTml) { var RefreshParams = refreshParamNxtActNewPub + '&' + refreshParamIdSes + '&' + refreshParamWho; objXMLHttpReqNewTml.onreadystatechange = readNewTimelineData; objXMLHttpReqNewTml.open('POST',ActionAJAX,true); objXMLHttpReqNewTml.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); objXMLHttpReqNewTml.send(RefreshParams); } } ● Automatic refresh via AJAX ● every 2 s → 3 s → 4 s → 5 s... just_now_timeline_list _____ |_____| |_____| |_____| | __v__ |_____| |_____| |_____| |_____| new_timeline_list
  • 103. Timeline: showing publications function readNewTimelineData () { if (objXMLHttpReqNewTml.readyState == 4) // Check if data have been received if (objXMLHttpReqNewTml.status == 200) { // Access to UL for just now timeline var justNowTimeline = document.getElementById('just_now_timeline_list'); if (justNowTimeline) { // Update list of publications in just now timeline justNowTimeline.innerHTML = objXMLHttpReqNewTml.responseText; var numNotesJustGot = justNowTimeline.childNodes.length; if (numNotesJustGot) {// New notes received // Scripts in timeline got via AJAX are not executed ==> execute them evalScriptsInElem (justNowTimeline); // Process maths MathJax.typeset(); // Move all the LI elements (notes) in UL 'just_now_timeline_list'... // ...to the top of UL 'new_timeline_list' var newTimeline = document.getElementById('new_timeline_list'); for (var i=0; i<numNotesJustGot; i++) { // Move node from just now timeline to new timeline newTimeline.insertBefore(justNowTimeline.lastChild,newTimeline.firstChild); newTimeline.firstChild.className += " Tml_NEW_PUB"; } // Update number of notes in new timeline var viewNewCount = document.getElementById('view_new_count'); viewNewCount.innerHTML = newTimeline.childNodes.length; // Unhide message with number of notes if hidden var viewNewContainer = document.getElementById('view_new_container'); viewNewContainer.style.display = ''; } } // Global delay variable is set initially in swad-core delayNewTml += 1000; // Increase one second on each call setTimeout('refreshNewTml()',delayNewTml); } } just_now_timeline_list _____ |_____| |_____| |_____| | __v__ |_____| |_____| |_____| |_____| new_timeline_list
  • 104. Timeline: showing publications function moveNewTimelineToTimeline () { // Move the LI elements (notes) in UL 'new_timeline_list'... // ...to the top of UL 'timeline_list', only if not repeated before var newTimeline = document.getElementById('new_timeline_list'); var numNewNotes = newTimeline.childNodes.length; if (numNewNotes) { var timeline = document.getElementById("timeline_list"); for (var i=1; i<=numNewNotes; i++) { // Check if the last child (the oldest) in the new timeline... // ...is the last ocurrence of the note var mostRecentOcurrenceOfNote = true; var lastChildIndex = numNewNotes - i; var noteCode = newTimeline.lastChild.dataset.noteCode; for (var j=0; j<lastChildIndex; j++) if (newTimeline.childNodes[j].dataset.noteCode == noteCode) { mostRecentOcurrenceOfNote = false; break; } // Move or remove node from new timeline if (mostRecentOcurrenceOfNote) { // Move node from new timeline to timeline timeline.insertBefore(newTimeline.lastChild,timeline.firstChild); timeline.firstChild.className += " Tml_NEW_PUB"; } else // Remove last child (because is repeated in more recent pubs) newTimeline.removeChild(newTimeline.lastChild); } } // Reset number of new publications after moving var viewNewCount = document.getElementById('view_new_count'); viewNewCount.innerHTML = 0; // Hide link to view new publications after moving var viewNewContainer = document.getElementById('view_new_container'); viewNewContainer.style.display = 'none'; } new_timeline_list _____ |_____| |_____| |_____| |_____| | See new activity (4) __v__ |_____| |_____| |_____| |_____| |_____| |_____| |_____| timeline_list
  • 105. Timeline: showing publications // This function is called when user clicks in 'See more' var objXMLHttpReqOldTml = false; function refreshOldTimeline () { objXMLHttpReqOldTml = AJAXCreateObject (); // new XMLHttpRequest() if (objXMLHttpReqOldTml) { var refreshParams = refreshParamNxtActOldPub + '&' + refreshParamIdSes; if (typeof refreshParamUsr !== 'undefined') { if (refreshParamUsr.length) refreshParams += '&' + refreshParamUsr; } if (typeof refreshParamWho !== 'undefined') { if (refreshParamWho.length) refreshParams += '&' + refreshParamWho; } objXMLHttpReqOldTml.onreadystatechange = readOldTimelineData; objXMLHttpReqOldTml.open('POST',actionAJAX,true); objXMLHttpReqOldTml.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); objXMLHttpReqOldTml.send(refreshParams); } } ● View old publications: when user clicks "See more..." timeline_list _____ |_____| |_____| |_____| |_____| |_____| |_____| |_____| ^ See more __|__ |_____| |_____| |_____| |_____| |_____| |_____| |_____| old_timeline_list
  • 106. Timeline: showing publications function readOldTimelineData () { if (objXMLHttpReqOldTml.readyState == 4) // Check if data have been received if (objXMLHttpReqOldTml.status == 200) { // Access to UL with the old timeline var oldTimeline = document.getElementById('old_timeline_list'); if (oldTimeline) { // Fill list of publications in old timeline oldTimeline.innerHTML = objXMLHttpReqOldTml.responseText; var countOldTimeline = oldTimeline.childNodes.length; if (countOldTimeline) { // Scripts in timeline got via AJAX are not executed ==> execute them evalScriptsInElem (oldTimeline); // Process maths MathJax.typeset(); // Move all the LI elements in UL 'old_timeline_list' // to the bottom of UL 'timeline_list' var timeline = document.getElementById("timeline_list"); for (var i=0; i<countOldTimeline; i++) timeline.appendChild(oldTimeline.firstChild); // There may be more publications // Unhide icon to be hidden on click document.getElementById('get_old_timeline').style.display = ''; // Hide icon to be shown on click document.getElementById('getting_old_timeline').style.display = 'none'; } else // No old publications retrieved, so we have reached the oldest publication // Hide container with link to get old publications document.getElementById("view_old_pubs_container").style.display = 'none'; } } } timeline_list _____ |_____| |_____| |_____| |_____| |_____| |_____| |_____| ^ See more __|__ |_____| |_____| |_____| |_____| |_____| |_____| |_____| old_timeline_list
  • 107. Layout: notes ___________________________________________ | | | Top message: | > top message |___________________________________________| / | _____ | | | || | | Author's name | Date-time | | | ||Auth.| |______________________|___________| | | ||photo| | | | author's | ||_____| | | > name, time | | | Note | | and content | | | content | | | | | | | | | |__________________________________| / | | | | | | | | | Favs | Shared |Remove| | > note | |_____________|_____________|______| | | |________| | | | | | List | | buttons | | Comment| of | > and | | icon | comments | | comments | |________|__________________________________| | | | | | | | Form to write new comment | | | |__________________________________| / /
  • 108. Layout: comments ___________________________________________ | _____ | | | || | | Author's name | Date-time | | | ||Auth.| |______________________|___________| | | ||photo| | | | author's | ||_____| | | > name, time | | | Comment | | and content > comment | | content | | | | | | | | | |__________________________________| / | | | | | | | | Favs |Remove| > buttons | |________|___________________________|______| / /
  • 109. Layout: comments Before clicking "See prev..." --> After clicking "See prev..." _________________________________ _________________________________ | div con_<id> | | div con_<id> | | (hidden) | | (visible) | | _____________________________ | | _____________________________ | | | v See only the latest | | | | v See only the latest | | | |_________(contract)__________| | | |_________(contract)__________| | |_________________________________| |_________________________________| _________________________________ _________________________________ | div <id> | | div <id> updated | | which content | | _____________________________ | | will be updated via AJAX | | | ul com_<id> | | | (parent of parent of form) | | | _________________________ | | | | | | | li (comment 1) | | | | | | | |_________________________| | | | | | | | ... | | | | | | | |_________________________| | | | | | | | li (comment n) | | | | | --> | | |_________________________| | | | | | |_____________________________| | | _____________________________ | | _____________________________ | | | div exp_<id> | | | | div exp_<id> | | | | (visible) | | | | (hidden) | | | | _________________________ | | | | | | | | | form | | | | | | | | | | _____________________ | | | | | _____________________ | | | | | | ^ See prev.comments | | | | | | | ^ See prev.comments | | | | | | |_______(expand)______| | | | | | |_______(expand)______| | | | | |_________________________| | | | | | | | |_____________________________| | | |_____________________________| | |_________________________________| |_________________________________| _________________________________ _________________________________ | ul | | ul | | _________________________ | | _________________________ | | | li (comment n+1) | | | | li (comment n+1) | | | |_________________________| | | |_________________________| | | | ... | | | | ... | | | |_________________________| | | |_________________________| | | | li (comment m) | | | | li (comment m) | | | |_________________________| | | |_________________________| | |_________________________________| |_________________________________|
  • 110. Layout: favs & shared _container_____________________________________________ | _<id>_med_ico | | |____Clip_____| | | | | _container <id>_med_upl_(initially hidden)_________ | | | _box___________________________________________ | | | | | ? | | | | | | Multimedia | | | | | | | | | | | | _prefs_container___________________ | | | | | | | _pref_container_________________ | | | | | | | | | _______ _______ _______ | | | | | | | | | | | Image/| |YouTube| | Embed | | | | | | | | | | | |_video_| |_______| |_______| | | | | | | | | | |_______________________________| | | | | | | | |___________________________________| | | | | | | _file_container____________________________ | | | | | | | ___________ | | | | | | | | |_Browse..._| No file selected. | | | | | | | |___________________________________________| | | | | | | _URL_container_____________________________ | | | | | | | _______________________________________ | | | | | | | | |_Link__________________________________| | | | | | | | |___________________________________________| | | | | | | _title_container___________________________ | | | | | | | _______________________________________ | | | | | | | | |_Title/attribution_____________________| | | | | | | | |___________________________________________| | | | | | |_______________________________________________| | | | |___________________________________________________| | |_______________________________________________________|
  • 111. Layout: favs & shared ___________________________________________________________________________ | div which content will be updated (parent of parent of form) | | _____________________ _______ _____________________________________ | | | div (parent of form)| | div | | div for users | | | | _________________ | | for | | ______ ______ ______ ______ | | | | | this form | | | num. | | | | | | | | | form | | | | | | _____________ | | | of | | | user | | user | | user | | to | | | | | | | fav icon | | | | users | | | 1 | | 2 | | 3 | | show | | | | | | |_____________| | | | | | | | | | | | | all | | | | | |_________________| | | | | |______| |______| |______| |______| | | | |_____________________| |_______| |_____________________________________| | |___________________________________________________________________________| typedef enum { Tml_Usr_SHOW_FEW_USRS, // Show a few first favers/sharers Tml_Usr_SHOW_ALL_USRS, // Show all favers/sharers } Tml_Usr_HowManyUsrs_t;
  • 112. Future objectives and tasks “When they ask me when a program will be ready, I answer: it depends on how much you work on it.” Richard Stallman Future objectives and tasks “When they ask me when a program will be ready, I answer: it depends on how much you work on it.” Richard Stallman
  • 113. Future objectives and tasks ● Objective 1: Incorporate new functionalities in the platform and improve some of the existing ones for its integration with gamification, geolocation and EDM Objective 1 tasks T1.1 Instructional design + planning T1.5 Improved test exams T1.2 Monitoring + activity reports T1.6 Scanning homework with the mobile T1.3 Collaborative edition (wiki) T1.7 Integrated grades T1.4 Improved schedule + calendar T1.8 Enhanced forums + chat + messages
  • 114. Future objectives and tasks ● Objective 2: Integration of gamification based on typical game elements in the functionalities of the web platform and the mobile app Objective 2 tasks T2.1 ARS integrated (interactive games with remote control) T2.2 Scores + badges in global and course functionalities T2.3 Karma in timeline, forums and files T2.4 Progress bars in user profiles and courses
  • 115. Future objectives and tasks ● Objective 3: Integration of indoor geolocation to improve the location of users in institutional dependencies and attendance control Objective 3 tasks T3.1 Database + location prototype T3.5 Possible improvements • Alerts about friends that are close • Display location on map • QR to check-in • Store history for activity reports and recommendations T3.2 SWAD API functions T3.3 Integration in SWADroid T3.4 Add gamification
  • 116. Future objectives and tasks ● Objective 4: Integrate Educational Data Mining techniques to improve student assessment, identify study tips, and offer alerts to students and teachers Objective 4 tasks T4.1 Study state of the art of EDM (lines of research, articles) T4.2 Study algorithms + software tools T4.3 Off-platform experiments (predict + recommend + alert) T4.4 Select algorithms and integrate them into the platform
  • 117. Future objectives and tasks ● Objective 5: Analyze educational changes in motivation and participation, results, and degree of use and satisfaction after the improvements Objective 5 tasks T5.1 Interviews with users prior to the improvement T5.2 Acquire reference data prior to improvement T5.3 Measure indicators after improvement: performance, use, motivation ... T5.4 Disseminate partial and final results
  • 118. Conclusions “We are free, we can be wide open" Analyse, The Cranberries Conclusions “We are free, we can be wide open" Analyse, The Cranberries
  • 119. Conclusions ● We have developed and used an educational platform for 21 years at UGR (Spain) ● It’s a fast tool that consumes very few computing resources, making it suitable for low-cost installations
  • 120. Conclusions ● It had a great growth between 2005 and 2015 ● In 2015 it was almost used by the entire UGR (≈60K students) ● In total, it has been used by 195,000 users at UGR
  • 121. Conclusions ● Since 2010 it’s free software, so anyone can install it (and improve it) ● Since 2012 it is freely available in the cloud for everyone, in the portal OpenSWAD.org ● Of course, you can try it at https://openswad.org/
  • 122. Conclusions ● Since 2016 its use at UGR has decreased due to institutional support to another official platform ● However, we have continued working on the improvement of the platform ● We will continue its upgrade with gamification, geolocation and data mining, among other features
  • 123. Thank you! Antonio Cañas University of Granada (UGR) @acanasvargas acanas@ugr.es acanas@openswad.org https://openswad.org/ @openswad Thank you! Antonio Cañas University of Granada (UGR) @acanasvargas acanas@ugr.es acanas@openswad.org https://openswad.org/ @openswad 123 123 Antonio Cañas Vargas