The CDSS package (course dependent skill structures)
provides a way to quickly develop a rough competence structure for an
existing course. The basic idea is to identify, for each lesson of the
course, the skills taught by that lesson and required for understanding
that lessons, respectively. The interesting point is that only the
direct prerequisite skills have to be specified.
From this skill assignment, attribution functions (and possibly also
attribution relations) can be derived on the level of both, skills and
learning objects. These are then the basis for deriving and further
processing skills spaces and learning object spaces using functions,
e.g., of the kstMatrix package. On the other side, it is
also possible to derive a skill map through the
cdss_sa2mu() function which grounds a connection to the
CbKST package.
The resulting structures may well need further, manual refinement, e.g. with respect to falsely equivalent skills (see below).
Information on the assignment of skills to learning objects can be specified in the three most standard spreadsheet file formats (CSV, ODS, and XLSX). For ODS and XLSX files, two sheets are expected specifying assignment of taught and required skills respectively. For the CSV case, two distinct files are expected because CSV does not support for multi-sheet files.
Each sheet (or CSV each file) contains a table with two columns, learning object id and skill id. For each skill assigned to a learning object, there is a separate row. The table must contain a header row.
The CDSS package provides example data files in the
extdata directory.
fpath <- system.file("extdata", package="CDSS")
sa <- cdss_read_skill_assignment(paste0(fpath, "/SkillAssignment.ods"))
sa
#> $taught
#> a b c d e f g
#> l1 1 0 0 0 0 0 0
#> l2 0 1 0 0 0 0 0
#> l3 0 0 1 0 0 0 0
#> l4 0 0 1 0 0 0 0
#> l5 0 0 0 1 0 0 0
#> l6 0 0 0 0 1 0 0
#> l7 0 0 0 0 0 1 1
#> l8 0 0 0 0 0 1 1
#>
#> $required
#> a b c d e f g
#> l1 0 0 0 0 0 0 0
#> l2 0 0 0 0 0 0 0
#> l3 1 0 0 0 0 0 0
#> l4 0 1 0 0 0 0 0
#> l5 0 1 0 0 0 0 0
#> l6 0 0 1 0 0 0 0
#> l7 0 0 0 1 1 0 0
#> l8 0 0 0 1 0 0 0
#>
#> attr(,"class")
#> [1] "cdss_sa" "list"By default, skill assignments which do not hold certain properties,
are rejected. This behavior can be changed by setting the optional
parameter warnonly to TRUE.
cdss_read_skill_assignment_ods(paste0(fpath, "/ErroneousSkillAssignment.ods"), warnonly=TRUE)
#> Warning in cdss_read_skill_assignment_ods(paste0(fpath, "/ErroneousSkillAssignment.ods"), : 'cdss_read_skill_assignment_ods' is deprecated.
#> Use 'cdss_read_skill_assignment' instead.
#> See help("Deprecated")
#> $taught
#> c1 c2 c3 c5 c4 c6 c7
#> l1 1 0 0 0 0 0 0
#> l2 0 1 0 0 0 0 0
#> l3 0 0 1 0 0 0 0
#> l4 0 0 1 0 0 0 0
#> l5 0 0 0 1 0 0 0
#> l6 0 0 0 0 1 0 0
#> l7 0 0 0 0 0 1 0
#> l8 0 0 0 0 0 0 0
#>
#> $required
#> c1 c2 c3 c5 c4 c6 c7
#> l1 0 0 0 0 0 0 0
#> l2 0 0 0 0 0 0 0
#> l3 1 0 0 0 0 0 0
#> l4 0 1 0 0 0 0 0
#> l5 0 1 0 0 0 0 0
#> l6 0 0 1 0 0 0 0
#> l7 0 0 0 1 1 1 1
#> l8 0 0 0 1 0 0 0
#>
#> attr(,"class")
#> [1] "cdss_sa" "list"
#> [1] "Not all skills are taught by learning objects: "
#> [1] "c7"
#> [1] "Some skills are taught by and required for the same learning object: "
#> [1] "l7"
#> [1] "Not all learning objects teach something: "
#> [1] "l8"
#> [1] "The assignment tables are not skill assignment compliant!"
#> $taught
#> c1 c2 c3 c5 c4 c6 c7
#> l1 1 0 0 0 0 0 0
#> l2 0 1 0 0 0 0 0
#> l3 0 0 1 0 0 0 0
#> l4 0 0 1 0 0 0 0
#> l5 0 0 0 1 0 0 0
#> l6 0 0 0 0 1 0 0
#> l7 0 0 0 0 0 1 0
#> l8 0 0 0 0 0 0 0
#>
#> $required
#> c1 c2 c3 c5 c4 c6 c7
#> l1 0 0 0 0 0 0 0
#> l2 0 0 0 0 0 0 0
#> l3 1 0 0 0 0 0 0
#> l4 0 1 0 0 0 0 0
#> l5 0 1 0 0 0 0 0
#> l6 0 0 1 0 0 0 0
#> l7 0 0 0 1 1 1 1
#> l8 0 0 0 1 0 0 0
#>
#> attr(,"class")
#> [1] "cdss_sa" "list"Figure 1 shows an overall view of the possible workflow(s) within the
CDSS package including the interfacing points to the
kstMatrix and CbKST packages.
Figure 1: CDSS workflow
There are two ways to derive the skill structure from the skill
assignment, through an attribution function or through a skill (multi)
map. Both ways lead to the same skill structure. Further processing then
has to be done using functions from the kstMatrix and
CbKSTpackages.
af <- cdss_skill_sa2af(sa) # Attribution function
af
#> Skill a b c d e f g
#> 2 a 1 0 0 0 0 0 0
#> 3 b 0 1 0 0 0 0 0
#> 4 c 1 0 1 0 0 0 0
#> 5 c 0 1 1 0 0 0 0
#> 6 d 0 1 0 1 0 0 0
#> 7 e 0 0 1 0 1 0 0
#> 8 f 0 0 0 1 1 1 1
#> 9 f 0 0 0 1 0 1 1
#> 10 g 0 0 0 1 1 1 1
#> 11 g 0 0 0 1 0 1 1
plot(kmspace(kmbasis(kmclosure(af))))FIgure 2: Derived skill space
mu <- cdss_sa2mu(sa) # Skill multi map
mu
#> LO a b c d e f g
#> 1 l1 1 0 0 0 0 0 0
#> 2 l2 0 1 0 0 0 0 0
#> 3 l3 1 0 1 0 0 0 0
#> 4 l4 0 1 1 0 0 0 0
#> 5 l5 0 1 0 1 0 0 0
#> 6 l6 1 0 1 0 1 0 0
#> 7 l6 0 1 1 0 1 0 0
#> 8 l8 0 1 0 1 0 1 1
#> 9 l7 0 1 1 1 1 1 1
plot(kmspace(kmbasis(cbkst_competencestructure(mu))))FIgure 3: Dweriving a skill space through the skill multi map
For LO structures, things are similar to but still slightly different from skill structures. Again, we have two ways to derive an LO space but the meaning of the LO states is different and thus are the spaces. The straightforward definition of an LO state would be the set of LOs the learner has visited. The respective LO space is achieved using the attribution function way. For a skill (multi) map, however, the LO state of a learner is the set of LOs whose (required and taught) skills this learner has. One can also have a look at the possible learning paths through the LO space.
laf <- cdss_lo_sa2af(sa) # Attribution function
laf
#> LO l1 l2 l3 l4 l5 l6 l7 l8
#> 2 l1 1 0 0 0 0 0 0 0
#> 3 l2 0 1 0 0 0 0 0 0
#> 4 l3 1 0 1 0 0 0 0 0
#> 5 l4 0 1 0 1 0 0 0 0
#> 6 l5 0 1 0 0 1 0 0 0
#> 7 l6 0 0 1 0 0 1 0 0
#> 8 l6 0 0 0 1 0 1 0 0
#> 9 l7 0 0 0 0 1 1 1 0
#> 10 l8 0 0 0 0 1 0 0 1
lospc <- kmspace(kmbasis(kmclosure(laf)))
plot(lospc)FIgure 4: LO space derived through the attribution function
lp <- kmlearningpaths(lospc)
length(lp)
#> [1] 340
lp[[1]]
#> [[1]]
#> [1] "∅"
#>
#> [[2]]
#> [1] "{l1}"
#>
#> [[3]]
#> [1] "{l1, l2}"
#>
#> [[4]]
#> [1] "{l1, l2, l3}"
#>
#> [[5]]
#> [1] "{l1, l2, l3, l4}"
#>
#> [[6]]
#> [1] "{l1, l2, l3, l4, l5}"
#>
#> [[7]]
#> [1] "{l1, l2, l3, l4, l5, l6}"
#>
#> [[8]]
#> [1] "{l1, l2, l3, l4, l5, l6, l8}"
#>
#> [[9]]
#> [1] "{l1, l2, l3, l4, l5, l6, l7, l8}"
#>
#> attr(,"class")
#> [1] "kmlearningpath" "list"
lp[[2]]
#> [[1]]
#> [1] "∅"
#>
#> [[2]]
#> [1] "{l1}"
#>
#> [[3]]
#> [1] "{l1, l2}"
#>
#> [[4]]
#> [1] "{l1, l2, l3}"
#>
#> [[5]]
#> [1] "{l1, l2, l3, l4}"
#>
#> [[6]]
#> [1] "{l1, l2, l3, l4, l5}"
#>
#> [[7]]
#> [1] "{l1, l2, l3, l4, l5, l6}"
#>
#> [[8]]
#> [1] "{l1, l2, l3, l4, l5, l6, l7}"
#>
#> [[9]]
#> [1] "{l1, l2, l3, l4, l5, l6, l7, l8}"
#>
#> attr(,"class")
#> [1] "kmlearningpath" "list"FIgure 5: LO space derived through the skill multi map
The latter LO space has 37 states while the former one has 42 states.
CDSS stands for course-dependent skill structures. This means that a different course teaching the same set of skills will most probably lead to a different skill structure. That is, we do not give a perfect solution but rather a starting point for further development of the structure.
It may often occur that one learning object teaches multiple skills.
If there are no other learning objects teaching these skills in
different combinations, they will be deemed as equivalent although this
may just be a course-dependent artifact. In this case, a refinement o
the obrtained skill space may well be reasonable. The functions of the
kstMatrix package offer the right tools for this. In our
example space, e.g., the skills f and g are
equivalent. We remedy this by determining the intersection of this space
with a second one which makes f a prerequisite of
g.
FIgure 6: Refining a basis
extbas <- matrix(c(1,0,1,1), nrow=2, byrow=TRUE)
colnames(extbas) <- c("f", "g")
class(extbas) <- unique(c("kmbasis", "kmfamset", class(extbas)))
extbas
#> f g
#> [1,] 1 0
#> [2,] 1 1
#> attr(,"class")
#> [1] "kmbasis" "kmfamset" "matrix" "array"
newbas <-kmrefine(bas, extbas)
newbas
#> a b c d e f g
#> [1,] 1 0 0 0 0 0 0
#> [2,] 0 1 0 0 0 0 0
#> [3,] 1 0 1 0 0 0 0
#> [4,] 0 1 1 0 0 0 0
#> [5,] 0 1 0 1 0 0 0
#> [6,] 1 0 1 0 1 0 0
#> [7,] 0 1 1 0 1 0 0
#> [8,] 0 1 0 1 0 1 0
#> [9,] 0 1 0 1 0 1 1
#> attr(,"class")
#> [1] "kmfamset" "matrix" "array"
class(newbas)
#> [1] "kmfamset" "matrix" "array"FIgure 7: Refined basis