---
title: "CDSS"
subtitle: "Course--Dependent Skill Structures"
author: "Cord Hockemeyer"
date: "`{r} format(Sys.time(), '%B %d, %Y')`"
output: 
  html:
    options:
      number_sections: true
      fig_caption: true
      highlight: true
      toc: 
        depth: 3
vignette: >
  %\VignetteIndexEntry{CDSS}
  %\VignetteEngine{litedown::vignette}
  %\VignetteEncoding{UTF-8}
abstract: "The `CDSS` package provides A KISS (keep it simple, stupid) approach to derive a skill structure for an existing set of learning objects. Basis for the skill structure is the assignment of taught and required skills, respectively, to each learning object."
keywords: "knowledge space theory, skill structure, learning objects"
---

```{r setup, echo=FALSE}
library(CDSS)
library(kstMatrix)
# library(knitr)
```
# Introduction
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, a competence structure and a 
lesson structure can be derived with the `CDSS` functions. These functions cover the whole workflow from reading the skill
assignments from spreadsheet files up to the determination of surmise functions or surmise relations.

The resulting structure may well need further, manual refinement, e.g. with respect to falsely equivalent skills (see [below](#sec:dealing-with-equivalence-classes)).

# Skill assignment data files
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 XLSYX 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 provide for multi-sheet files.

Each sheet (or CSV 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 may contain a header row; the reading functions (see below) assume by
default that it does.

# Workflow for the general case
Figure 1 shows the workflow for the general case, i.e. derivation of a surmise function from skill assignments in a course
where (some) competencies may be taught by several, alternative learning objects. The complete workflow is implemented in the
`cdss_wf_read_skill_assignment()` function but all individual steps can also be called individually.

![Figure 1: General CDSS Workflow](CDSS_Workflow.png){width=25%}

_Figure 1: General CDSS Workflow_

The first step is to read the skill assignment. There are three functions for that allowing for three different spreadsheet
file formats: `cdss_read_skill_assignment_csv()`, `cdss_read_skill_assignment_ods()`, and `cdss_read_skill_assignment_xlsx()`
for CSV (comma-separated values) files, LibreOffice/OpenOffice files, or Excel files, respectively. The tables read from the file are then converted into a skill assignment object after checking compliance to the properties of such objects.

The next conversions are from a skill assignment to a skill multi-assignment and a complete skill multi-assignment using
`cdss_sa2sma()` and `cdss_sma2csma()`. In the final step, a surmise function is determined with `cdss_csma2sf()`. 


# Workflow for the simplified case
In the _simplified case,_ there is exactly one teaching learning object for each skill (there may still be several taught
skills assigned to the same learning object). In this case, the resulting structures of skills and learning objects, respectively, are quasi-ordinal knowledge spaces.

Figure 2 shows the respective workflow which is briefly described underneath.

![Figure 2: Simplified CDSS Workflow](CDSS_Simplified_Workflow_Skills.png){width=70%} 

_Figure 2: Simplified CDSS Workflow_

After reading a skill assignment object using one of the functions mentioned in the [previous section](#sec:workflow-for-the-general-case), the applicability of this workflow is checked, i.e. whether there is truly
only one teaching learning object per skill. In the positive case, an _attribution relation_ can be derived using `cdss_sa2ar_skill()` which can then be closed to a surmise relation by callin `cdss_close_ar()`.

# Learning object structures
It is also possible to derive structures on the learning objects from the skill assignment. Currently, there exist three respective functions:

- `cdss_lo_csma2sf()` determines a surmise function on the set of learning objects based on a complete skill 
   multi-assignment object.
- `cdss_lo_sa2af()` determines an attribution function from a skill assignment object. However, currently, there is no 
   function available to close the attribution function to a surmise function.
- `cdss_lo_sa2ar()` derives an attribution relation from a skill assignment object. This attribution relation can then 
   be closed to a surmise relation using `cdss_close_ar()`. This function is only applicable in the aforementioned 
   _simple case_.

Surmise relations on learning objects may be applied for adaptive teaching. For example, [Moodle](https://moodle.org)
allows to specify prerequisite relations betgween diferent lessons/learning objects.

# Further processing

## General further processing with the `kstMatrix` package
The surmise functions and surmise relations built following the above workflows can be further processed using the
`kstMatrix` package (Hockemeyer, Steiner, & Wong, 2026). In a first step, the respective basis can be determined using 
`kstMatrix::kmbasis()` method. This opens the way to other tasks like constructing the knowledge space, plotting space 
or basis, or simulating response patterns from the space.

## Dealing with equivalence classes
One issue with the CDSS approach is that learning objects may teach multiple skills. This often leads to equivalence
classes of skills where the skills are not really equivalent but the equivalence is just induced by the connection to 
the same learning object. A manual fine-tuning may well be appropriate.

One could determine the equivalence classes using `kstmatrix::kmnotions()`. After saving the basis to a spreadsheet file 
with `kstIO::write_kbase()`, this file can be edited with the respective spreadsheet program. Simply add rows which
lead to a structure within the equivalence class(es). Afterward re-import the changed basis into R with `kstIO::read_kbase()` and process that changed basis further.

# Examples

## General workflow
In a first example, we do the whole workflow at once for a skill assignment table which does not describe a surmise relation, i.e. there are some skills taught by several learning objects. The resulting `sflist` contains `NULL` values for `srs` and `srl` accordingly. In a final step, we determine and plot the basis of the resulting skill space.
``` {r example}
fpath <- system.file("extdata", "SkillAssignment.xlsx", package="CDSS")
sflist <- cdss_wf_read_skill_assignment(fpath)
sflist
b <- kstMatrix::kmbasis(sflist$sfs)
b
```
Figure 3 shows the Hasse diagram of the basis (using the `plot()` method of the `kstMatrix` package).
```{r basis-figure, echo=FALSE}
pl <- plot(b)
# rsvg::rsvg_png(charToRaw(DiagrammeRsvg::export_svg(pl)), paste0(tempdir(), file="/plot3.png", width=2000))
bm <- rsvg::rsvg(charToRaw(DiagrammeRsvg::export_svg(pl)), width=1500)
png::writePNG(bm, paste0(tempdir(), file="/plot3.png"))
```
!["Example basis"](`{r} paste0(tempdir(), "/plot3.png")`){width=65%}

_Figure 3: Derived example basis_

_**Remarks**_

1. This basis does not belong to a quasi-ordinal space and, therefore, cannot be represented by a surmise relation:
   for example, the intersection of the states _{a,c}_ and _{b,c}_, i.e. _{c}_ is not a state.
2. The skills _f_ and _g_ are equivalent (cf. [previous section](#sec:dealing-with-equivalence-classes).
3. For technical reasons (with grViz and RMarkdown) the plot is manually included here but if you execute the code,
   e.g., in RStudio, the plot will be shown in the Viewer pane.
   
## Skill assignment tables
The skill assignment tables are given below, first the taught and then the required skills.
``` {r sat, echo=FALSE}
fpath <- system.file("extdata", "SkillAssignment-T.csv", package="CDSS")
read.csv(fpath)
fpath <- system.file("extdata", "SkillAssignment-R.csv", package="CDSS")
read.csv(fpath)
```

Please note that learning objects 1 and 2 do not have any prerequisite skills.

## Workflow for the simplified case
In this example, we do the individual steps. We use a derivation of the skill assignment used [above](#sec:general-workflow). First, we read the file and check whether it can be represented through a surmise relation.
```{r simplified}
fpath <- system.file("extdata", "SkillAssignment_SR.xlsx", package="CDSS")
sa <- cdss_read_skill_assignment_xlsx(fpath)
sa
cdss_sa_describes_sr(sa)
```
Subsequently, we build the attribution relation and its closure to a surmise relation.
```{r surmise}
ar <- cdss_sa2ar_skill(sa)
ar
sr <- cdss_close_ar(ar)
sr
```
Figure 4 shows the Hasse diagram of the surmise relation (again using the `plot()` method of the `kstMatrix` package).
```{r surmise-figure, echo=FALSE}
pl <- plot(sr)
# rsvg::rsvg_png(charToRaw(DiagrammeRsvg::export_svg(pl)), paste0(tempdir(), file="/plot4.png", width=1000))
bm <- rsvg::rsvg(charToRaw(DiagrammeRsvg::export_svg(pl)), width=1000)
png::writePNG(bm, paste0(tempdir(), file="/plot4.png"))
```
!["Example surmise relation"](`{r} paste0(tempdir(), "/plot4.png")`){width=19%}

_Figure 4: Derived example surmise system_

Please note that the skills _f_ and _g_ are equivalent.

# References
- Hockemeyer C, Steiner P, & Wong W (2026). _kstMatrix: Basic Functions in Knowledge Space Theory Using Matrix
Representation_. doi:10.32614/CRAN.package.kstMatrix, R package
version 2.3-1, <https://CRAN.R-project.org/package=kstMatrix>.
