Skip to content

Commit

Permalink
Merge pull request #98 from CurricularAnalytics/development
Browse files Browse the repository at this point in the history
Version 1.0.3
  • Loading branch information
haydenfree authored Aug 5, 2020
2 parents 6e9a1bc + 35c64dd commit f5fb8bc
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 64 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ julia:
- 1.1
- 1.2
- 1.3
- 1.4
- 1.5


jobs:
include:
- stage: "Documentation"
julia: 1.1
julia: 1.0.5
os: linux
script:
- julia --project=docs/ -e 'using Pkg; Pkg.instantiate(); Pkg.develop(PackageSpec(path=pwd()))'
Expand Down
62 changes: 28 additions & 34 deletions Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ version = "0.0.4"
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[CSV]]
deps = ["CategoricalArrays", "DataFrames", "Dates", "FilePathsBase", "Mmap", "Parsers", "PooledArrays", "Tables", "Unicode", "WeakRefStrings"]
git-tree-sha1 = "c5ef3e34d21aa4b0e88521f1dc8031515d389148"
deps = ["CategoricalArrays", "DataFrames", "Dates", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode"]
git-tree-sha1 = "a390152e6850405a48ca51bd7ca33d11a21d6230"
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
version = "0.5.26"
version = "0.7.7"

[[CategoricalArrays]]
deps = ["Compat", "DataAPI", "Future", "JSON", "Missings", "Printf", "Reexport", "Statistics", "Unicode"]
git-tree-sha1 = "23d7324164c89638c18f6d7f90d972fa9c4fa9fb"
deps = ["DataAPI", "Future", "JSON", "Missings", "Printf", "Statistics", "Unicode"]
git-tree-sha1 = "a6c17353ee38ddab30e73dcfaa1107752de724ec"
uuid = "324d7699-5711-5eae-9e2f-1d82baa6b597"
version = "0.7.7"
version = "0.8.1"

[[Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "48c20c43e157c6eab6cf88326504ec042b05e456"
git-tree-sha1 = "a6a8197ae253f2c1a22b2ae17c2dfaf5812c03aa"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.10.0"
version = "3.13.0"

[[DataAPI]]
git-tree-sha1 = "176e23402d80e7743fc26c19c681bfb11246af32"
Expand All @@ -34,15 +34,15 @@ version = "1.3.0"

[[DataFrames]]
deps = ["CategoricalArrays", "Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "Missings", "PooledArrays", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
git-tree-sha1 = "7d5bf815cc0b30253e3486e8ce2b93bf9d0faff6"
git-tree-sha1 = "4fe99dbfb5201c5766d20d32a65209434347fd58"
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
version = "0.20.2"
version = "0.21.6"

[[DataStructures]]
deps = ["InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "af6d9c86e191c917c2276fbede1137e8ea20157f"
git-tree-sha1 = "88d48e133e6d3dd68183309877eac74393daa7eb"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.17.17"
version = "0.17.20"

[[DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
Expand All @@ -63,22 +63,16 @@ uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[DocStringExtensions]]
deps = ["LibGit2", "Markdown", "Pkg", "Test"]
git-tree-sha1 = "88bb0edb352b16608036faadcc071adda068582a"
git-tree-sha1 = "c5714d9bcdba66389612dc4c47ed827c64112997"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.1"
version = "0.8.2"

[[Documenter]]
deps = ["Base64", "Dates", "DocStringExtensions", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"]
git-tree-sha1 = "395fa1554c69735802bba37d9e7d9586fd44326c"
uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
version = "0.24.11"

[[FilePathsBase]]
deps = ["Dates", "LinearAlgebra", "Printf", "Test", "UUIDs"]
git-tree-sha1 = "2cd6e2e7965934f72cb80251f760228e2264bab3"
uuid = "48062228-2e41-5def-b9a4-89aafe57970f"
version = "0.7.0"

[[Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
Expand Down Expand Up @@ -149,15 +143,15 @@ version = "0.4.3"
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[OrderedCollections]]
git-tree-sha1 = "12ce190210d278e12644bcadf5b21cbdcf225cd3"
git-tree-sha1 = "293b70ac1780f9584c89268a6e2a560d938a7065"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.2.0"
version = "1.3.0"

[[Parsers]]
deps = ["Dates", "Test"]
git-tree-sha1 = "0c16b3179190d3046c073440d94172cfc3bb0553"
git-tree-sha1 = "10134f2ee0b1978ae7752c41306e131a684e1f06"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "0.3.12"
version = "1.0.7"

[[Pkg]]
deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
Expand Down Expand Up @@ -190,6 +184,12 @@ version = "0.2.0"
[[SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[SentinelArrays]]
deps = ["Dates", "Random"]
git-tree-sha1 = "7871163033b83a0d08bb601af56488c6f642a113"
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
version = "1.2.10"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

Expand Down Expand Up @@ -218,9 +218,9 @@ uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "5c06c0aeb81bef54aed4b3f446847905eb6cbda0"
git-tree-sha1 = "016d1e1a00fabc556473b07161da3d39726ded35"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "0.12.3"
version = "0.12.4"

[[Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
Expand All @@ -234,9 +234,9 @@ version = "1.0.0"

[[Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
git-tree-sha1 = "c45dcc27331febabc20d86cb3974ef095257dcf3"
git-tree-sha1 = "b7f762e9820b7fab47544c36f26f54ac59cf8abf"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.0.4"
version = "1.0.5"

[[Test]]
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
Expand All @@ -248,9 +248,3 @@ uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[WeakRefStrings]]
deps = ["DataAPI", "Random", "Test"]
git-tree-sha1 = "28807f85197eaad3cbd2330386fac1dcb9e7e11d"
uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5"
version = "0.6.2"
10 changes: 5 additions & 5 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "CurricularAnalytics"
uuid = "593ffa3d-269e-5d81-88bc-c3b6809c35a6"
authors = ["Greg Heileman <gregheileman@gmail.com>", "Hayden Free <hayden.free@uky.edu>", "Orhan Abar <orhan.abar@uky.edu>", "Will Thompson <wgthompson@uky.edu>"]
version = "1.0.2"
version = "1.0.3"

[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
Expand All @@ -15,9 +15,9 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[compat]
CSV = "0.5.9"
DataFrames = "0.20.0"
CSV = "0.7"
DataFrames = "0.21.0"
DataStructures = "0.17.0"
Documenter = "0.24.0"
LightGraphs = "1.2.0"
julia = "1.0.5, 1.1, 1.2, 1.3, 1.4"
LightGraphs = "1.3.0"
julia = "1.0.5, 1.1, 1.2, 1.3, 1.4, 1.5"
4 changes: 2 additions & 2 deletions src/CSVUtilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ function csv_line_reader(line::AbstractString, delimeter::Char=',')
end

function find_cell(row, header)
if !(header in names(row)) #I assume this means if header is not in names
return ""
if !(string(header) in names(row)) #I assume this means if header is not in names
error("$(header) column is missing")
elseif typeof(row[header]) == Missing
return ""
else
Expand Down
11 changes: 6 additions & 5 deletions src/CurricularAnalytics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ include("DegreePlanCreation.jl")

export AA, AAS, AS, BA, BS, Course, CourseCatalog, Curriculum, Degree, DegreePlan, EdgeClass, LearningOutcome, Requisite, System, Term, add_course!,
add_lo_requisite!, add_requisite!, all_paths, basic_metrics, basic_statistics, bin_filling, blocking_factor, centrality, co, compare_curricula,
complexity, course, course_from_id, course_from_vertex, course_id, courses_from_vertices, create_degree_plan, dead_ends, delay_factor, delete_requisite!,
dfs, extraneous_requisites, find_term, gad, homology, is_duplicate, isvalid_curriculum, isvalid_degree_plan, longest_path, longest_paths, merge_curricula,
pre, print_plan, quarter, reach, reach_subgraph, reachable_from, reachable_from_subgraph, reachable_to, reachable_to_subgraph, read_csv, requisite_distance,
requisite_type, semester, similarity, strict_co, topological_sort, total_credits, write_csv, Grade, grade, AbstractRequirement, CourseSet, RequirementSet,
CourseRecord, StudentRecord, TransferArticulation, add_transfer_catalog, add_transfer_course, transfer_equiv
complexity, convert_ids, course, course_from_id, course_from_vertex, course_id, courses_from_vertices, create_degree_plan, dead_ends, delay_factor,
delete_requisite!, dfs, extraneous_requisites, find_term, gad, homology, is_duplicate, isvalid_curriculum, isvalid_degree_plan, longest_path,
longest_paths, merge_curricula, pre, print_plan, quarter, reach, reach_subgraph, reachable_from, reachable_from_subgraph, reachable_to,
reachable_to_subgraph, read_csv, requisite_distance, requisite_type, semester, similarity, strict_co, topological_sort, total_credits, write_csv,
Grade, grade, AbstractRequirement, CourseSet, RequirementSet, CourseRecord, StudentRecord, TransferArticulation, add_transfer_catalog,
add_transfer_course, transfer_equiv

# Check if a curriculum graph has requisite cycles.
"""
Expand Down
52 changes: 48 additions & 4 deletions src/DataTypes/Course.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Course-related data DataTypes

abstract type AbstractCourse end

##############################################################
# Course data type
"""
Expand All @@ -21,7 +25,7 @@ Keyword:
julia> Course("Calculus with Applications", 4, prefix="MA", num="112", canonical_name="Calculus I")
```
"""
mutable struct Course
mutable struct Course <: AbstractCourse
id::Int # Unique course id
vertex_id::Dict{Int, Int} # The vertex id of the course w/in a curriculum graph, stored as
# (curriculum_id, vertex_id)
Expand Down Expand Up @@ -70,6 +74,46 @@ mutable struct Course
end
end

mutable struct CourseCollection <: AbstractCourse
id::Int # Unique course id
vertex_id::Dict{Int, Int} # The vertex id of the course w/in a curriculum graph, stored as
# (curriculum_id, vertex_id)
courses::Array{Course} # Courses associated with the collection
name::AbstractString # Name of the course, e.g., Introduction to Psychology
credit_hours::Real # Number of credit hours associated with a "typcial" course in the collection
institution::AbstractString # Institution offering the course
college::AbstractString # College or school (within the institution) offering the course
department::AbstractString # Department (within the school or college) offering the course
canonical_name::AbstractString # Standard name used to denote the course collection, e.g., math genearl education
requisites::Dict{Int, Requisite} # List of requisites, in (requisite_course id, requisite_type) format
metrics::Dict{String, Any} # Course-related metrics
metadata::Dict{String, Any} # Course-related metadata

# Constructor
function CourseCollection(name::AbstractString, credit_hours::Real, courses::Array{Course,1}; institution::AbstractString="",
college::AbstractString="", department::AbstractString="", canonical_name::AbstractString="", id::Int=0)
this = new()
this.name = name
this.credit_hours = credit_hours
this.courses = courses
this.institution = institution
if id == 0
this.id = mod(hash(this.name * this.institution * string(length(courses))), UInt32)
else
this.id = id
end
this.college = college
this.department = department
this.canonical_name = canonical_name
this.requisites = Dict{Int, Requisite}()
#this.requisite_formula
this.metrics = Dict{String, Any}()
this.metadata = Dict{String, Any}()
this.vertex_id = Dict{Int, Int}() # curriculum id -> vertex id
return this
end
end

function course_id(prefix::AbstractString, num::AbstractString, name::AbstractString, institution::AbstractString)
convert(Int, mod(hash(name * prefix * num * institution), UInt32))
end
Expand All @@ -85,7 +129,7 @@ One of the following requisite types must be specified for `rc`:
- `co` : a co-requisite course that may be taken before or at the same time as `tc`.
- `strict_co` : a strict co-requisite course that must be taken at the same time as `tc`.
"""
function add_requisite!(requisite_course::Course, course::Course, requisite_type::Requisite)
function add_requisite!(requisite_course::AbstractCourse, course::AbstractCourse, requisite_type::Requisite)
course.requisites[requisite_course.id] = requisite_type
end

Expand All @@ -100,7 +144,7 @@ The following requisite types may be specified for `rc`:
- `co` : a co-requisite course that may be taken before or at the same time as `tc`.
- `strict_co` : a strict co-requisite course that must be taken at the same time as `tc`.
"""
function add_requisite!(requisite_courses::Array{Course}, course::Course, requisite_types::Array{Requisite})
function add_requisite!(requisite_courses::Array{AbstractCourse}, course::AbstractCourse, requisite_types::Array{Requisite})
@assert length(requisite_courses) == length(requisite_types)
for i = 1:length(requisite_courses)
course.requisites[requisite_courses[i].id] = requisite_types[i]
Expand All @@ -119,7 +163,7 @@ The following requisite types may be specified for `rc`:
- `co` : a co-requisite course that may be taken before or at the same time as `tc`.
- `strict_co` : a strict co-requisite course that must be taken at the same time as `tc`.
"""
function delete_requisite!(requisite_course::Course, course::Course)
function delete_requisite!(requisite_course::AbstractCourse, course::AbstractCourse)
#if !haskey(course.requisites, requisite_course.id)
# error("The requisite you are trying to delete does not exist")
#end
Expand Down
38 changes: 36 additions & 2 deletions src/DataTypes/Curriculum.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ mutable struct Curriculum
degree_type::Degree # Type of degree_type
system_type::System # Semester or quarter system
CIP::AbstractString # CIP code associated with the curriculum
courses::Array{Course} # Array of required courses in curriculum
courses::Array{AbstractCourse} # Array of required courses in curriculum
num_courses::Int # Number of required courses in curriculum
credit_hours::Real # Total number of credit hours in required curriculum
graph::SimpleDiGraph{Int} # Directed graph representation of pre-/co-requisite structure
Expand All @@ -43,7 +43,7 @@ mutable struct Curriculum
metadata::Dict{String, Any} # Curriculum-related metadata

# Constructor
function Curriculum(name::AbstractString, courses::Array{Course}; learning_outcomes::Array{LearningOutcome}=Array{LearningOutcome,1}(),
function Curriculum(name::AbstractString, courses::Array{AbstractCourse}; learning_outcomes::Array{LearningOutcome}=Array{LearningOutcome,1}(),
degree_type::Degree=BS, system_type::System=semester, institution::AbstractString="", CIP::AbstractString="",
id::Int=0, sortby_ID::Bool=true)
this = new()
Expand Down Expand Up @@ -76,13 +76,37 @@ mutable struct Curriculum
end
return this
end

function Curriculum(name::AbstractString, courses::Array{Course}; learning_outcomes::Array{LearningOutcome}=Array{LearningOutcome,1}(),
degree_type::Degree=BS, system_type::System=semester, institution::AbstractString="", CIP::AbstractString="",
id::Int=0, sortby_ID::Bool=true)
Curriculum(name, convert(Array{AbstractCourse},courses), learning_outcomes=learning_outcomes, degree_type=degree_type,
system_type=system_type, institution=institution, CIP=CIP, id=id, sortby_ID=sortby_ID)
end
end

# TODO: update a curriculum graph if requisites have been added/removed or courses have been added/removed
#function update_curriculum(curriculum::Curriculum, courses::Array{Course}=())
# # if courses array is empty, no new courses were added
#end

# Converts course ids, from those used in CSV file format, to the standard hashed id used by the data structures in the toolbox
function convert_ids(curriculum::Curriculum)
for c1 in curriculum.courses
old_id = c1.id
c1.id = mod(hash(c1.name * c1.prefix * c1.num * c1.institution), UInt32)
if old_id != c1.id
for c2 in curriculum.courses
if old_id in keys(c2.requisites)
add_requisite!(c1, c2, c2.requisites[old_id])
delete!(c2.requisites, old_id)
end
end
end
end
return curriculum
end

# Map course IDs to vertex IDs in an underlying curriculum graph.
function map_vertex_ids(curriculum::Curriculum)
mapped_ids = Dict{Int, Int}()
Expand All @@ -92,6 +116,16 @@ function map_vertex_ids(curriculum::Curriculum)
return mapped_ids
end

# Compute the hash value used to create the id for a course, and return the course if it exists in the curriculum supplied as input
function course(curric::Curriculum, prefix::AbstractString, num::AbstractString, name::AbstractString, institution::AbstractString)
hash_val = mod(hash(name * prefix * num * institution), UInt32)
if hash_val in collect(c.id for c in curric.courses)
return curric.courses[findfirst(x->x.id==hash_val, curric.courses)]
else
error("Course: $prefix $num: $name at $institution does not exist in curriculum: $(curric.name)")
end
end

# Return the course associated with a course id in a curriculum
function course_from_id(curriculum::Curriculum, id::Int)
for c in curriculum.courses
Expand Down
Loading

2 comments on commit f5fb8bc

@haydenfree
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/19058

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.0.3 -m "<description of version>" f5fb8bc0cfa7394b3b089d1f2dbfb1dc3064c6c1
git push origin v1.0.3

Please sign in to comment.