SlideShare une entreprise Scribd logo
1  sur  125
Télécharger pour lire hors ligne
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
●
Timeline
●
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?
What is SWAD?
This is how it looks,
although some parts of its appearance,
such as colors or icons, are customizable
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
Advertisements
Teachers / month 2014 2021 (OpenSWAD)
→
Advertisements
Students / month 2014 2021 (OpenSWAD)
→
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
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
Former servers at the UGR
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
HTML5
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)
●
Bate Ye (iSWAD)
●
Javier Bueno López (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)
typedef enum
{
Tml_Pub_UNKNOWN = 0,
Tml_Pub_ORIGINAL_NOTE = 1,
Tml_Pub_SHARED_NOTE = 2,
Tml_Pub_COMMENT_TO_NOTE = 3,
} Tml_Pub_Type_t;
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.
7 for timeline.
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.)
| |_____|
| |_____|
 |_____|
<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...
_____
/ |_____| 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 < |_____|
| |_____|
| |_____|
 |_____|
Timeline: showing publications
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);
}
}
_____
/ |_____| 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 < |_____|
| |_____|
| |_____|
 |_____|
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 not executed ==> execute them
evalScriptsInElem (justNowTimeline);
// Process maths
MathJax.typeset();
...
_____
/ |_____| 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 < |_____|
| |_____|
| |_____|
 |_____|
Timeline: showing publications
...
// 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
| |_____|
| |_____|
| |
Hidden < __v__
| |_____| new_timeline_list
| |_____|
| |_____|
 |_____|
|
See new activity (0)
__v__
/ |_____| timeline_list
| |_____|
Visible | |_____|
on < |_____|
page | |_____|
| |_____|
 |_____|
^
See more
__|__
/ |_____| old_timeline_list
| |_____|
| |_____|
Hidden < |_____|
| |_____|
| |_____|
 |_____|
_____
/ |_____| 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 < |_____|
| |_____|
| |_____|
 |_____|
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;
}
...
●
User clicks "See new activity" → View new pubs.
Timeline: showing publications
...
// 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';
}
_____
/ |_____| 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 < |_____|
| |_____|
| |_____|
 |_____|
_____
/ |_____| 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 < |_____|
| |_____|
| |_____|
 |_____|
Timeline: showing publications
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);
}
}
●
User clicks "See more..." → View old pubs.
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 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);
...
_____
/ |_____| 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 < |_____|
| |_____|
| |_____|
 |_____|
Timeline: showing publications
...
// 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 pub.
// Hide container with link to get old publications
document.getElementById("view_old_pubs_container").style.display = 'none';
}
}
}
_____
/ |_____| 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 < |_____|
| |_____|
| |_____|
 |_____|
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: multimedia
_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
125
125
Antonio Cañas Vargas

Contenu connexe

Similaire à Swad Timeline

Online learning platforms
Online learning platformsOnline learning platforms
Online learning platformsSergio Cigoli
 
JCP & The Future of Java
JCP & The Future of JavaJCP & The Future of Java
JCP & The Future of JavaHeather VanCura
 
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 geospatialLluís Vicens
 
Dashboards voor learning analytics
Dashboards voor learning analyticsDashboards voor learning analytics
Dashboards voor learning analyticsSURF Events
 
Will Postgres Live Forever?
Will Postgres Live Forever?Will Postgres Live Forever?
Will Postgres Live Forever?EDB
 
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 Tracy Kent
 
DSC Aswan University info session
DSC Aswan University info sessionDSC Aswan University info session
DSC Aswan University info sessionAhmedHany131
 
Top 10 Big Data Technologies | Edureka
Top 10 Big Data Technologies | EdurekaTop 10 Big Data Technologies | Edureka
Top 10 Big Data Technologies | EdurekaEdureka!
 
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 | Accentureaccenture
 
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 BriefingBenito Gonzalez
 
JavaOne Latin America Participate in Shaping Java's Future
JavaOne Latin America Participate in Shaping Java's Future JavaOne Latin America Participate in Shaping Java's Future
JavaOne Latin America Participate in Shaping Java's Future Heather VanCura
 
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 ChangeNeil Chue Hong
 
GDSC USeP - Infosession 2023.pptx
GDSC USeP - Infosession 2023.pptxGDSC USeP - Infosession 2023.pptx
GDSC USeP - Infosession 2023.pptxjrmaldeza00117
 
Technology and Digital Platform | 2019 partner summit
Technology and Digital Platform | 2019 partner summitTechnology and Digital Platform | 2019 partner summit
Technology and Digital Platform | 2019 partner summitAndrew Kumar
 
Osgis2011 edina addy_pope
Osgis2011 edina addy_popeOsgis2011 edina addy_pope
Osgis2011 edina addy_popeAddy Pope
 
Osgis2011 edina addy_pope
Osgis2011 edina addy_popeOsgis2011 edina addy_pope
Osgis2011 edina addy_popeAddy Pope
 
Grand Challenges Learning Analytics
Grand Challenges Learning AnalyticsGrand Challenges Learning Analytics
Grand Challenges Learning Analyticsamberg
 
SGCI - The Science Gateways Community Institute: International Collaboration ...
SGCI - The Science Gateways Community Institute: International Collaboration ...SGCI - The Science Gateways Community Institute: International Collaboration ...
SGCI - The Science Gateways Community Institute: International Collaboration ...Sandra Gesing
 
Google summer of code with drupal
Google summer of code with drupalGoogle summer of code with drupal
Google summer of code with drupalNaveen Valecha
 

Similaire à Swad Timeline (20)

Online learning platforms
Online learning platformsOnline learning platforms
Online learning platforms
 
JCP & The Future of Java
JCP & The Future of JavaJCP & The Future of Java
JCP & The Future of Java
 
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
 
QuSandbox+NVIDIA Rapids
QuSandbox+NVIDIA RapidsQuSandbox+NVIDIA Rapids
QuSandbox+NVIDIA Rapids
 
Dashboards voor learning analytics
Dashboards voor learning analyticsDashboards voor learning analytics
Dashboards voor learning analytics
 
Will Postgres Live Forever?
Will Postgres Live Forever?Will Postgres Live Forever?
Will Postgres Live Forever?
 
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
 
DSC Aswan University info session
DSC Aswan University info sessionDSC Aswan University info session
DSC Aswan University info session
 
Top 10 Big Data Technologies | Edureka
Top 10 Big Data Technologies | EdurekaTop 10 Big Data Technologies | Edureka
Top 10 Big Data Technologies | Edureka
 
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
 
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
 
JavaOne Latin America Participate in Shaping Java's Future
JavaOne Latin America Participate in Shaping Java's Future JavaOne Latin America Participate in Shaping Java's Future
JavaOne Latin America Participate in Shaping Java's Future
 
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
 
Technology and Digital Platform | 2019 partner summit
Technology and Digital Platform | 2019 partner summitTechnology and Digital Platform | 2019 partner summit
Technology and Digital Platform | 2019 partner summit
 
Osgis2011 edina addy_pope
Osgis2011 edina addy_popeOsgis2011 edina addy_pope
Osgis2011 edina addy_pope
 
Osgis2011 edina addy_pope
Osgis2011 edina addy_popeOsgis2011 edina addy_pope
Osgis2011 edina addy_pope
 
Grand Challenges Learning Analytics
Grand Challenges Learning AnalyticsGrand Challenges Learning Analytics
Grand Challenges Learning Analytics
 
SGCI - The Science Gateways Community Institute: International Collaboration ...
SGCI - The Science Gateways Community Institute: International Collaboration ...SGCI - The Science Gateways Community Institute: International Collaboration ...
SGCI - The Science Gateways Community Institute: International Collaboration ...
 
Google summer of code with drupal
Google summer of code with drupalGoogle summer of code with drupal
Google summer of code with drupal
 

Dernier

Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....ShaimaaMohamedGalal
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 

Dernier (20)

Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 

Swad Timeline

  • 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 ● Timeline ● 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. What is SWAD? This is how it looks, although some parts of its appearance, such as colors or icons, are customizable
  • 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. Advertisements Teachers / month 2014 2021 (OpenSWAD) →
  • 54. Advertisements Students / month 2014 2021 (OpenSWAD) →
  • 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. 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 Former servers at the UGR
  • 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 HTML5 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) ● Bate Ye (iSWAD) ● Javier Bueno López (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) typedef enum { Tml_Pub_UNKNOWN = 0, Tml_Pub_ORIGINAL_NOTE = 1, Tml_Pub_SHARED_NOTE = 2, Tml_Pub_COMMENT_TO_NOTE = 3, } Tml_Pub_Type_t; 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. 7 for timeline. 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.) | |_____| | |_____| |_____| <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>
  • 100. 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... _____ / |_____| 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 < |_____| | |_____| | |_____| |_____|
  • 101. Timeline: showing publications 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); } } _____ / |_____| 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 < |_____| | |_____| | |_____| |_____|
  • 102. 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 not executed ==> execute them evalScriptsInElem (justNowTimeline); // Process maths MathJax.typeset(); ... _____ / |_____| 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 < |_____| | |_____| | |_____| |_____|
  • 103. Timeline: showing publications ... // 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 | |_____| | |_____| | | Hidden < __v__ | |_____| new_timeline_list | |_____| | |_____| |_____| | See new activity (0) __v__ / |_____| timeline_list | |_____| Visible | |_____| on < |_____| page | |_____| | |_____| |_____| ^ See more __|__ / |_____| old_timeline_list | |_____| | |_____| Hidden < |_____| | |_____| | |_____| |_____|
  • 104. _____ / |_____| 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 < |_____| | |_____| | |_____| |_____| 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; } ... ● User clicks "See new activity" → View new pubs.
  • 105. Timeline: showing publications ... // 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'; } _____ / |_____| 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 < |_____| | |_____| | |_____| |_____|
  • 106. _____ / |_____| 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 < |_____| | |_____| | |_____| |_____| Timeline: showing publications 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); } } ● User clicks "See more..." → View old pubs.
  • 107. 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 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); ... _____ / |_____| 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 < |_____| | |_____| | |_____| |_____|
  • 108. Timeline: showing publications ... // 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 pub. // Hide container with link to get old publications document.getElementById("view_old_pubs_container").style.display = 'none'; } } } _____ / |_____| 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 < |_____| | |_____| | |_____| |_____|
  • 109. 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 | | | |__________________________________| / /
  • 110. Layout: comments ___________________________________________ | _____ | | | || | | Author's name | Date-time | | | ||Auth.| |______________________|___________| | | ||photo| | | | author's | ||_____| | | > name, time | | | Comment | | and content > comment | | content | | | | | | | | | |__________________________________| / | | | | | | | | Favs |Remove| > buttons | |________|___________________________|______| / /
  • 111. 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) | | | |_________________________| | | |_________________________| | |_________________________________| |_________________________________|
  • 112. Layout: multimedia _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_____________________| | | | | | | | |___________________________________________| | | | | | |_______________________________________________| | | | |___________________________________________________| | |_______________________________________________________|
  • 113. 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;
  • 114. 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
  • 115. 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
  • 116. 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
  • 117. 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
  • 118. 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
  • 119. 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
  • 120. Conclusions “We are free, we can be wide open" Analyse, The Cranberries Conclusions “We are free, we can be wide open" Analyse, The Cranberries
  • 121. 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
  • 122. 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
  • 123. 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/
  • 124. 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
  • 125. 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 125 125 Antonio Cañas Vargas