Molding CSV data — continuing the exploration
This is Part 5 of Tutorial: molding CSV data into an explainable system. This last part lets you explore on your own to model and mold venues and design studies . Instead of giving you step-by-step instructions, you are just given general directions to explore.
If you are jumping into the tutorial at this point, and have some previously saved work not already in this image, you should file it in now. Otherwise, you can file in a sample snapshot reflecting the work completed at the end of the previous part:
VRTutorialExamples new fileIn13Mondrian
We still have some obvious domain entities left to model. The procedure is the same as before.
This time you should do everything without any hints.
⇒
Introduce a VRVenue entity. A venue has a conference name and a year, as well as a number of papers. You'll want to keep a dictionary of venues in the dataset object, keyed by both venue name and year. Each venue should also have views of its papers and authors. Conversely, authors will have views of the venues they have attended.
VRDatasetExamples new vrDataset
Here's a possible list of changes. Yours could differ in various ways ...
"protocol: #accessing"
VRPaper >> venueName
^ self data at: 'Venue'
"protocol: #accessing"
VRPaper >> year
^ self data at: 'Year'
VRDomainEntity << #VRVenue
slots: { #name . #papers . #year };
tag: 'Model';
package: 'VisualisationReview'.
VRDomainEntity class << VRVenue class
slots: {}
accessing
"protocol: #accessing"
VRVenue >> name
^ name
"protocol: #accessing"
VRVenue >> name: aString
name := aString
"protocol: #accessing"
VRVenue >> papers
^ papers
"protocol: #accessing"
VRVenue >> year
^ year
"protocol: #accessing"
VRVenue >> year: aString
year := aString
initialization
"protocol: #initialization"
VRVenue >> addPaper: aPaper
papers add: aPaper
"protocol: #initialization"
VRVenue >> initialize
papers := OrderedCollection new
instance creation
"protocol: #'instance creation'"
VRVenue class >> named: aString year: anotherString in: aDataset
^ self new
name: aString;
year: anotherString;
dataset: aDataset;
yourself
"protocol: #initialization"
VRDataset >> initializeVenueDict
"NB: Venues have both names and years, so the dictionary must be index on both."
| dict |
dict := Dictionary new.
self allPapers
do: [ :p |
(dict
at: {p venueName.
p year}
ifAbsentPut: [ VRVenue
named: p venueName
year: p year
in: self ]) addPaper: p ].
^ dict
Object << #VRDataset
slots: { #allJSON . #selectedJSON . #paperDict . #authorDict . #venueDict };
tag: 'Model';
package: 'VisualisationReview'.
Object class << VRDataset class
slots: {}
"protocol: #accessing"
VRDataset >> venueDict
^ venueDict ifNil: [ venueDict := self initializeVenueDict ]
"protocol: #querying"
VRDataset >> venueNamed: aString year: anotherString
^ self venueDict
at: {aString.
anotherString}
VRDomainEntityGroup << #VRVenueGroup
slots: {};
tag: 'Model';
package: 'VisualisationReview'.
VRDomainEntityGroup class << VRVenueGroup class
as yet unclassified
"protocol: #'as yet unclassified'"
VRVenueGroup >> gtVenuesFor: aView
<gtView>
^ aView columnedList
title: 'Venues';
items: [ self items ];
column: 'Index'
text: [ :eachItem :eachIndex | eachIndex asRopedText foreground: Color gray ]
width: 45;
column: 'Name' text: [ :each | each name ];
column: 'Year' text: [ :each | each year ];
actionUpdateButton
"protocol: #'as yet unclassified'"
VRVenueGroup >> gtVenuesFor: aView
<gtView>
^ aView columnedList
title: 'Venues';
items: [ self items ];
column: 'Index'
text: [ :eachItem :eachIndex | eachIndex asRopedText foreground: Color gray ]
width: 45;
column: 'Name' text: [ :each | each name ];
column: 'Year' text: [ :each | each year ];
column: '# Papers' text: [ :each | each papers size ];
actionUpdateButton
"protocol: #accessing"
VRDataset >> venues
^ VRVenueGroup
withAll: (self venueDict values
sort: [ :a :b | a year <= b year and: [ a name <= b name ] ])
"protocol: #views"
VRDataset >> gtVenuesFor: aView
<gtView>
^ aView forward
title: 'Venues';
object: [ self venues ];
view: #gtVenuesFor:
views
"protocol: #views"
VRVenue >> gtSummaryFor: aView
<gtView>
^ aView columnedList
title: 'Summary';
priority: 10;
items: [ {{'Name'.
self name}.
{'Year'.
self year}.
{'# Papers'.
self papers size}} ];
column: 'Key'
text: #first
width: 100;
column: 'Value' text: #second;
actionUpdateButton
"protocol: #accessing"
VRVenue >> papers
^ VRPaperGroup withAll: papers
"protocol: #views"
VRVenue >> gtPapersFor: aView
<gtView>
^ aView forward
title: 'Papers';
priority: 20;
object: [ self papers ];
view: #gtItemsFor:
"protocol: #accessing"
VRVenue >> authors
^ VRAuthorGroup
withAll: (((self papers flatCollect: #authors) copyWithout: self) copyWithoutDuplicates
sortedAs: #name)
"protocol: #views"
VRVenue >> gtAuthorsFor: aView
<gtView>
^ aView forward
title: 'Authors';
priority: 30;
object: [ self authors ];
view: #gtAuthorsFor:
"protocol: #printing"
VRVenue >> printOn: aStream
aStream
nextPutAll: self name;
nextPutAll: ': ';
nextPutAll: self year
"protocol: #accessing"
VRPaper >> venue
^ self dataset venueNamed: self venueName year: self year
"protocol: #views"
VRPaper >> gtSummaryFor: aView
<gtView>
^ aView columnedList
title: 'Summary';
priority: 10;
items: [ {{'ID'.
self id}.
{'Title'.
self title}.
{'Type'.
self type}.
{'# Authors'.
self data at: '# Authors'}.
{'# Pages'.
self data at: '# Pages'}.
{'Is selected'.
self isDesignStudy}.
{'Venue'.
self venue}} ];
column: 'Key'
text: #first
width: 100;
column: 'Value' text: #second;
send: #last;
actionUpdateButton
"protocol: #accessing"
VRAuthor >> venues
^ VRVenueGroup withAll: (self papers collect: #venue) copyWithoutDuplicates
"protocol: #views"
VRAuthor >> gtVenuesFor: aView
<gtView>
^ aView forward
title: 'Venues';
priority: 50;
object: [ self venues ];
view: #gtVenuesFor:
To sync to this point in the tutorial (throwing away any other changes) evaluate:
VRTutorialExamples new fileIn14Venues
We still haven't touched the second CSV file!
⇒
Create a VRDesignStudy entity with a data slot. Generate a dictionary of design studies in the dataset object, keyed by the id of the associated paper.
⇒
Create a summary view for design studies including the most important data.
⇒
Add a
Design studies
view to the dataset.
⇒
Link design studies to their papers and vice versa.
VRDatasetExamples new vrDataset
Here are some of the changes you might make:
VRDomainEntity << #VRDesignStudy
slots: { #data };
tag: 'Model';
package: 'VisualisationReview'.
VRDomainEntity class << VRDesignStudy class
slots: {}
accessing
"protocol: #accessing"
VRDesignStudy >> data
^ data
"protocol: #accessing"
VRDesignStudy >> data: anObject
data := anObject
accessing
"protocol: #accessing"
VRDesignStudy class >> for: title in: anObject
instance creation
"protocol: #'instance creation'"
VRDesignStudy class >> for: title in: anObject
"protocol: #'instance creation'"
VRDesignStudy class >> for: title in: anObject
"protocol: #'instance creation'"
VRDesignStudy class >> for: aDictionary in: aDataset
^ self new
data: aDictionary;
dataset: aDataset;
yourself
"protocol: #accessing"
VRDataset >> initializeDesignStudyDict
| dict |
dict := Dictionary new.
self selectedJSON
do: [ :d | dict at: (d at: 'ID') ifAbsentPut: (VRDesignStudy for: d in: self) ].
^ dict
Object << #VRDataset
slots: { #allJSON . #selectedJSON . #paperDict . #authorDict . #venueDict . #designStudyDict };
tag: 'Model';
package: 'VisualisationReview'.
Object class << VRDataset class
slots: {}
"protocol: #accessing"
VRDataset >> designStudyDict
^ designStudyDict ifNil: [ designStudyDict := self initializeDesignStudyDict ]
VRDomainEntityGroup << #VRDesignStudyGroup
slots: {};
tag: 'Model';
package: 'VisualisationReview'.
VRDomainEntityGroup class << VRDesignStudyGroup class
views
"protocol: #views"
VRDesignStudyGroup >> gtDesignStudiesFor: aView
<gtView>
^ aView columnedList
title: 'Design studies';
items: [ self items ];
column: 'Index'
text: [ :eachItem :eachIndex | eachIndex asRopedText foreground: Color gray ]
width: 45;
column: 'Title' text: [ :each | each title ];
actionUpdateButton
"protocol: #accessing"
VRDesignStudy >> title
^ self data at: 'Title'
printing
"protocol: #printing"
VRDesignStudy >> printOn: aStream
aStream nextPutAll: self title
"protocol: #accessing"
VRDesignStudy >> id
^ (self data at: 'ID') asNumber
"protocol: #accessing"
VRDataset >> designStudies
^ VRDesignStudyGroup withAll: (self designStudyDict values sortedAs: #title)
"protocol: #views"
VRDataset >> gtVenuesFor: aView
<gtView>
^ aView forward
title: 'Venues';
priority: 40;
object: [ self venues ];
view: #gtVenuesFor:
"protocol: #views"
VRDataset >> gtDesignStudiesFor: aView
<gtView>
^ aView forward
title: 'Design studies';
priority: 50;
object: [ self designStudies ];
view: #gtDesignStudiesFor:
"protocol: #accessing"
VRDesignStudy >> paper
^ self dataset paperWithId: self id
"protocol: #accessing"
VRDataset >> initializeDesignStudyDict
| dict |
dict := Dictionary new.
self selectedJSON
do: [ :d | dict at: (d at: 'ID') asNumber ifAbsentPut: (VRDesignStudy for: d in: self) ].
^ dict
"protocol: #accessing"
VRDesignStudy >> venueName
^ self data at: 'Venue'
"protocol: #accessing"
VRDesignStudy >> year
^ self data at: 'Paper Year'
"protocol: #accessing"
VRDesignStudy >> venue
^ self dataset venueNamed: self venueName year: self year
"protocol: #accessing"
VRDesignStudy >> abstract
^ self data at: 'Abstract'
"protocol: #'as yet unclassified'"
VRDesignStudy >> gtSummaryFor: aView
<gtView>
^ aView columnedList
title: 'Summary';
priority: 10;
items: [ {{'ID'.
self id}.
{'Paper'.
self paper} .
{'Abstract'.
self abstract} .
{'Venue'.
self venue} }];
column: 'Key'
text: #first
width: 100;
column: 'Value' text: #second;
send: #last;
actionUpdateButton
"protocol: #views"
VRDesignStudy >> gtJsonFor: aView
<gtView>
^ aView forward
title: 'Json';
priority: 20;
object: [ self data ];
view: #gtItemsFor:
"protocol: #accessing"
VRPaper >> designStudy
self isDesignStudy ifFalse: [ ^ nil ].
^ self dataset designStudyDict at: self id
"protocol: #views"
VRPaper >> gtSummaryFor: aView
<gtView>
^ aView columnedList
title: 'Summary';
priority: 10;
items: [ {{'ID'.
self id}.
{'Title'.
self title}.
{'Type'.
self type.
self designStudy}.
{'# Authors'.
self data at: '# Authors'}.
{'# Pages'.
self data at: '# Pages'}.
{'Is selected'.
self isDesignStudy}.
{'Venue'.
self venue}} ];
column: 'Key'
text: #first
width: 100;
column: 'Value' text: #second;
send: #last;
actionUpdateButton
To sync to this point in the tutorial (throwing away any other changes) evaluate:
VRTutorialExamples new fileIn15DesignStudies
NB: This page links to Pages containing missing references - allowed failures to allow references to missing classes and methods in this page.