Recent

Author Topic: Application - recommendations?  (Read 13298 times)

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Application - recommendations?
« on: September 22, 2017, 10:54:34 pm »
I'm planning on writing an application using Lazarus-Pascal.

Purpose:
Read csv with student names and ranking (secret to student).

Provide the following functions:

Randomly selection of a student (for presentation or other activity).

Create randomly generated groups (say of 3 or 4 students, customizable group size).

Create groups based on ranking, so that each group (of say 4 students) has 1 strong, 1 weak, and two middle ranking students.

Enable saving generated groups to files (e.g. csv), so they can be recalled.

Here are my initial thoughts on above.

Create record to store each students data.
Create array of records for up to say 40 students.

Don't use csv libraries (csvdocument, fpspreadsheet), but create simple textfile IO functions to access csv files (procedural). These functions read from file and store to record and vice versa for writing. Allow customization of cell / field delimiters. Advantage: application doesn't break when library does, and the operations required a very simple (doesn't make use of any of the advanced features possible in csv files).

GUI: Simple, no fancy stuff needed here, although drag-n-drop re-grouping could be nice. But, basically just need to display groups in a single window, with option for saving to file. Autonaming of groups based on prefix string concatenated with a number. Each section should have a title with group name and members listed in one or two lines.

Easy in RAD Lazarus-Pascal? Maybe with your help. Without help I'm kind of facing a very steep learning curve  :D 

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: Application - recommendations?
« Reply #1 on: September 22, 2017, 11:33:40 pm »
Look at the "TInifile" class, its in IniFiles unit..

 If allows you to create Section Names and Key names within each section.

 All key names can have set values of just about any type you can think of..

 This file format can be opened via NotePad if needed, it's all text format and setup
for groups sections etc..

 P.S.
   Be careful managed strings within records if you decide to write out the whole record to
file, you'll get corrupted data. If you ever want to do this use arrays of char's or Short strings.
The only true wisdom is knowing you know nothing

mas steindorff

  • Hero Member
  • *****
  • Posts: 532
Re: Application - recommendations?
« Reply #2 on: September 22, 2017, 11:48:53 pm »
I suggest you look into TStringslist.  you can use it's built in .loadfromfile()   and .savetofile() calls to simplify you learning curve for file access stuff. (use a  TloadFileDialog to ask for the file name later if you wish to handle several groups with the same program).
then each kid/record is just a ".string[]" so you can combine use /select each member. x can be a random number or whatever you wish.  check out the .count field to see how many kid you have in that group (file). you can add more info (beyond the kid's name) to expand the info if you wish.
windows 10 &11, Ubuntu 21+ - fpc 3.0.4, IDE 2.0 general releases

cpicanco

  • Hero Member
  • *****
  • Posts: 618
  • Behavioral Scientist and Programmer
    • Portfolio
Re: Application - recommendations?
« Reply #3 on: September 23, 2017, 03:09:42 pm »
Also, for csv I would suggest csvdocument unit. It has a parser for loading stuff (TCSVParser) and a class for random access to cells TCSVDocument.
Be mindful and excellent with each other.
https://github.com/cpicanco/

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Application - recommendations?
« Reply #4 on: September 23, 2017, 03:56:41 pm »
Easy in RAD Lazarus-Pascal? Maybe with your help. Without help I'm kind of facing a very steep learning curve  :D
The attached project shows one way to go about this task.

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Application - recommendations?
« Reply #5 on: September 24, 2017, 10:49:04 pm »
Look at the "TInifile" class, its in IniFiles unit..

I agree with the strengths of ini file format and have considered it in various other projects. However in this project I want to stick to the csv format.

Kind regards,
Michael



mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Application - recommendations?
« Reply #6 on: September 24, 2017, 10:51:45 pm »
I suggest you look into TStringslist.  you can use it's built in .loadfromfile()   and .savetofile() calls to simplify you learning curve for file access stuff. (use a  TloadFileDialog to ask for the file name later if you wish to handle several groups with the same program).
then each kid/record is just a ".string[]" so you can combine use /select each member. x can be a random number or whatever you wish.  check out the .count field to see how many kid you have in that group (file). you can add more info (beyond the kid's name) to expand the info if you wish.

I've been looking into TStringslist and it does look like a nice option.
I need to process data based on the ranking (integer). How do you suggest I extract this from TStringslist?

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Application - recommendations?
« Reply #7 on: September 24, 2017, 10:53:55 pm »
Also, for csv I would suggest csvdocument unit. It has a parser for loading stuff (TCSVParser) and a class for random access to cells TCSVDocument.

Do you recommend TCSVDocument over fpspreadsheet?

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Application - recommendations?
« Reply #8 on: September 24, 2017, 11:12:45 pm »

The attached project shows one way to go about this task.

Cool! I think I have learned a lot by browsing your code, thanks! (Still a lot to learn, though  8) )

In the unit uStudent, could you please elaborate on the purpose of the records: TStudent and TStudents. I understand the former, but what is the function of the latter? What is the function of the TStudentArray?

In mainStudents: Why is "uses uCreateStudentsDlg" placed after "implementation" whereas "uses uStudents" is placed earlier, between interface and type?

I wasn't clear on the idea with grouping. Idea is that all students must join a certain group. This means that when user presses "Create random groups" user should be asked about number of students per group, and the program should create sufficiently many groups so that all students end up in a group. Say there are 12 students and user specifies 4 students per group, then program should generate 3 groups.

In CreateRandomGroupButtonClick: What is purpose of rankSet, and how does Include(rankSet, r); work when basic type is Byte but r is an integer?

Regarding usage of the ranking parameter. The rank integer is a number I use to rank students according to performance. It doesn't align with number of students, instead it could follow a grading ranking, say numbers from 1 through 7 - even though there might be 30 students attending a class. This means several students will have the same rank and picking students for the balanced groups has to change a little.

Kind regards,
Michael
« Last Edit: September 24, 2017, 11:15:00 pm by mijen67 »

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: Application - recommendations?
« Reply #9 on: September 24, 2017, 11:29:25 pm »
Do you recommend TCSVDocument over fpspreadsheet?
It depends on what you want to do. If you only need data from a csv file then CSVDocument is enough (and in my opinion even this is an overkill for such simple files). If you need cell formatting and if your files will be read/written by Excel or LibreOffice Calc then fpspreadsheet may be worth trying (but you know that you can import csv files in these applications as well).

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Application - recommendations?
« Reply #10 on: September 25, 2017, 12:53:34 am »
In the unit uStudent, could you please elaborate on the purpose of the records: TStudent and TStudents. I understand the former, but what is the function of the latter? What is the function of the TStudentArray?
TStudent packages data for a single student.
TStudents is a container for managing a group of students. TStudentArray simply provides indexed access to such a group, and allows you to enumerate every student in the group (if need be).

In mainStudents: Why is "uses uCreateStudentsDlg" placed after "implementation" whereas "uses uStudents" is placed earlier, between interface and type?
The uCreateStudentsDlg unit is only needed in the implementation of the TForm1 method CreateStudentsButtonClick, so that unit's visibility can be restricted to the implementation section. Whereas uStudents has to be in the interface because the interface contains a TStudents field in the TForm1 class. That type is declared in uStudents.
Some people put all needed units in the interface, even if the interface does not require them, and only the implementation section needs a particular unit or two.
I prefer to make the distinction and only use units that are absolutely required. It seems a cleaner way of working. It also minimises the possibility of name clashes where tens or scores of units are named in uses clauses, because the more units are used, the greater the possibility that some unit inadvertently duplicates the name of a variable or other entity. Sometimes a name clash is evident because the clashing codes wont compile in each other's scope. But in some rare situations a duplicate name can cause a silent bug in which the variable you imagine is being changed is not, but another remote variable of the same name is being changed instead.

I wasn't clear on the idea with grouping. Idea is that all students must join a certain group. This means that when user presses "Create random groups" user should be asked about number of students per group, and the program should create sufficiently many groups so that all students end up in a group. Say there are 12 students and user specifies 4 students per group, then program should generate 3 groups.

I just implemented what I took to be your ideas based on a few lines of description which were not a full specification.
My intent was to give you ideas to adapt, not to read your mind about the details of what you actually wanted.

In CreateRandomGroupButtonClick: What is purpose of rankSet, and how does Include(rankSet, r); work when basic type is Byte but r is an integer?
To create a 'balanced' group requires sorting the larger group of students into sub-groups based on rank, and choosing student(s) from each sub-group. Sets are a straighforward way of creating such sub-groups, and determining if a given student is inside or outside that group.
In the CreateRandomGroupButtonClick method rankSet is used more simply as a way of both counting the number of students added to the group, and ensuring that the same student is not added twice (since students are picked at random, the same random number could easily reappear in the sequence of choices).
The compiler casts the Integer r to a Byte variable for you (since the two are assignment-compatible), though I could have made an explicit typecast. I could also have declared r as a Byte variable in the first place, but did not do so because it is generally faster to use native integer types. Not that it makes the slightest difference in this case.

Regarding usage of the ranking parameter. The rank integer is a number I use to rank students according to performance. It doesn't align with number of students, instead it could follow a grading ranking, say numbers from 1 through 7 - even though there might be 30 students attending a class. This means several students will have the same rank and picking students for the balanced groups has to change a little.
Again, your requirement and definition of "rank" was not clear to me from what was originally written.  So you will have to map your kind of rank to the simple ordering sequence I adopted. Or come up with a totally different approach.
« Last Edit: September 25, 2017, 12:57:35 am by howardpc »

cpicanco

  • Hero Member
  • *****
  • Posts: 618
  • Behavioral Scientist and Programmer
    • Portfolio
Re: Application - recommendations?
« Reply #11 on: September 25, 2017, 02:41:58 pm »
Also, for csv I would suggest csvdocument unit. It has a parser for loading stuff (TCSVParser) and a class for random access to cells TCSVDocument.

Do you recommend TCSVDocument over fpspreadsheet?

TCSVDocument is very simple and strainght to the point. All you need is to load/save csv files, right?
Be mindful and excellent with each other.
https://github.com/cpicanco/

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Application - recommendations?
« Reply #12 on: September 25, 2017, 05:47:40 pm »
Do you recommend TCSVDocument over fpspreadsheet?
It depends on what you want to do. If you only need data from a csv file then CSVDocument is enough (and in my opinion even this is an overkill for such simple files). If you need cell formatting and if your files will be read/written by Excel or LibreOffice Calc then fpspreadsheet may be worth trying (but you know that you can import csv files in these applications as well).

I agree this seems to be overkill for simple csv files. Could you give me hints on how to create my own simple parser?

Kind regards,
Michael

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Application - recommendations?
« Reply #13 on: September 25, 2017, 06:06:16 pm »
Some people put all needed units in the interface, even if the interface does not require them, and only the implementation section needs a particular unit or two.
I prefer to make the distinction and only use units that are absolutely required. It seems a cleaner way of working. It also minimises the possibility of name clashes where tens or scores of units are named in uses clauses, because the more units are used, the greater the possibility that some unit inadvertently duplicates the name of a variable or other entity. Sometimes a name clash is evident because the clashing codes wont compile in each other's scope. But in some rare situations a duplicate name can cause a silent bug in which the variable you imagine is being changed is not, but another remote variable of the same name is being changed instead.


Got it, thanks!

I just implemented what I took to be your ideas based on a few lines of description which were not a full specification.
My intent was to give you ideas to adapt, not to read your mind about the details of what you actually wanted.


Sure, I believe that assumptions of mind reading is something that wives use frequently and I will not go that path ;o)

In the CreateRandomGroupButtonClick method rankSet is used more simply as a way of both counting the number of students added to the group, and ensuring that the same student is not added twice (since students are picked at random, the same random number could easily reappear in the sequence of choices).
The compiler casts the Integer r to a Byte variable for you (since the two are assignment-compatible), though I could have made an explicit typecast. I could also have declared r as a Byte variable in the first place, but did not do so because it is generally faster to use native integer types. Not that it makes the slightest difference in this case.


Clever method, thanks!
Would it be possible to use a set of integers instead of bytes and avoid the casting? (not that I think it will make a difference but casting can theoretically lead to problems).


wp

  • Hero Member
  • *****
  • Posts: 11858
Re: Application - recommendations?
« Reply #14 on: September 25, 2017, 06:47:01 pm »
I agree this seems to be overkill for simple csv files. Could you give me hints on how to create my own simple parser?
It's all built into TStringlist. Use two stringlists, the first one reads the file, the seconds one gets the lines via its property DelimitedText. If the Delimiter of the 2nd stringlist is the delimiter used between the columns of the csv file then this operation splits up each line into its records.

Check this out:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   Classes;
  7.  
  8. var
  9.   lines, fields: TStringList;
  10.   i, j: Integer;
  11.  
  12. begin
  13.   lines := TStringList.Create;
  14.   try
  15.     fields := TStringList.Create;
  16.     try
  17.       fields.Delimiter := ';';  // This is the character which separates the columns
  18.       fields.StrictDelimiter := true;
  19.       lines.LoadFromFile('presidents.csv');
  20.       for i := 0 to lines.Count-1 do begin
  21.         fields.Delimitedtext := lines[i];
  22.         for j:= 0 to fields.Count-1 do
  23.           Write(fields[j]:20);
  24.         WriteLn;
  25.       end;
  26.     finally
  27.       fields.Free;
  28.     end;
  29.   finally
  30.     lines.Free;
  31.   end;
  32. end.
  33.  
  34. //------------------------------ snip --------------------------------
  35. // Here follows the data file "presidents.csv"
  36. //--------------------------------------------------------------------
  37. George Washington;1
  38. John Adams;2
  39. Thomas Jefferson;3
  40. James Madison;4
  41. James Monroe;5
  42. John Q. Adams;6
  43. Andrew Jackson;7
  44. Martin van Buren;8
  45. Willian H. Harrison;9
  46. John Tyler;10
  47. James K. Polk;11
  48. Zachary Taylor;12  
  49.  

 

TinyPortal © 2005-2018