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.