Δημοσιεύτηκε: 03 Μάιος 2012, 16:53
από migf1
Με αφορμή αυτό εδώ το post: http://forum.ubuntu-gr.org/viewtopic.ph ... 96#p240996, καθώς και τα περίπου 15 downloads που έγιναν τις τελευταίες 2 ημέρες (http://www.box.com/s/fb6b2fe18e2246ab22ec) αλλά και για να μη χαλάω το νήμα του Ηλία, ανοίγω νέο νήμα για αυτή την βιβλιοθήκη ζώων.

Σε εκείνο το νήμα η βιβλιοθήκη είναι σε εμβρυϊκό στάδιο. Έχει ήδη υποστεί πάααρα πολλές αλλαγές και στη δομή της και στη λειτουργικότητά της, και μάλιστα της έχω φτιάξει και τεκμηρίωση: http://x-karagiannis.gr/prog/libs/conte ... /doc/html/ (στο Modules παρουσιάζονται οι συναρτήσεις κατηγοριοποιημένες, ενώ στο Files->tanimal.h παρουσιάζονται αλφαβητικά).

Επειδή όμως είναι εξαιρετικά περιορισμένη για γενική χρήση, αποφάσισα να την κάνω πιο σφαιρική και πιο ευέλικτη. Θα την δουλεύω σιγά-σιγά και όσο χρόνο με πάρει. Οπότε δεν δίνω τον κώδικά της παραπάνω τεκμηρίωσης γιατί ήδη έχει υποστεί κι αυτός δραστικές αλλαγές (εκτός αν τον θέλει κανείς, οπότε γράψτε εδώ να τον ποστάρω).

Η μεγαλύτερη αλλαγή που κάνω αυτή τη στιγμή είναι η δυνατότητα να μπορούν να προστεθούν ζώα χωρίς να πειραχτεί καθόλου ο κώδικας της βιβλιοθήκης. Απλά με την προσθήκη 2 αρχείων ανά ζώο και την τροποποίηση ενός ακόμα, που περιέχει το ευρετήριο των ζώων.

Δηλαδή, υπάρχει ένα αρχείο ευρετήριο, το tanimal.idx με το id και το keyname του κάθε ζώου...

Μορφοποιημένος Κώδικας: Επιλογή όλων
* tanimal.idx
********************************************************
TANIMAL LIBRARY, ANIMAL INDEX FILE

freeware | copyright (c) 2012 migf1 <mig_f1@hotmail.com>
********************************************************

* ------------------------------------------------------
* Empty lines & lines STARTING with blanks or with the STAR
* symbol are IGNORED. Lines longer than 80 chars before the
* 1st star symbol are truncated.

TAID KeyName
---- -------
0 badger
1 bear
2 deer
3 duck
4 ferret
5 fox
6 hare
7 racoon
8 wild-boar
9 wolf

Αυτά είναι τα μέχρι-στιγμής προκαθορισμένα ζώα της βιβλιοθήκης. Για το καθένα από αυτά υπάρχει ένα data και ένα language αρχείο, με ονομασία το keyname του ζώου και κατάληξη .dat και .lng, αντίστοιχα.

Για παράδειγμα, για το 1ο ζώο (0 badger) έχουμε το data αρχείο badger.dat με τις default τιμές των χαρακτηριστικών του...

Μορφοποιημένος Κώδικας: Επιλογή όλων
* badger.dat
*******************************************************
TANIMAL LIBRARY, ANIMAL DATA FILE (EN)
Animal: BADGER (predefined)

freeware | copyright (c) 2012 migf1 <mig_f1@hotmail.com>
********************************************************
NOTES:
* Empty lines & lines STARTING with blanks or with the star symbol are ignored.
* Lines longer than 80 chars before the 1st star symbol get truncated
********************************************************

** Identification data (VERY IMPORTANT) -----------------
0 * Type Id (TAID)
badger * KeyName

** Specifications ---------------------------------------
60 * avg size (in cm)
13 * avg weight (in kg)
30 * top speed (in km/h)

** Other Attributes -------------------------------------
1 * Mood (0 = Scared, 1 = Calm, 2 = Angry)
100 * Health (0 = Dead, ... 100 = Healthy)

κι ένα language αρχείο badger.lng με τις γραμματικές ιδιαιτερότητες της επιλεγμένης γλώσσας, καθώς και το κείμενο της αναλυτικής του περιγραφής ( το book media info)...

Μορφοποιημένος Κώδικας: Επιλογή όλων
* badger.lng
********************************************************
TANIMAL LIBRARY, ANIMAL LANGUAGE FILE (EL)
Animal: BADGER (predefined)

freeware | copyright (c) 2012 migf1 <mig_f1@hotmail.com>
********************************************************

* Grammar Part
* ------------------------------------------------------
* Empty lines & lines STARTING with blanks or with the STAR
* symbol are IGNORED. Lines longer than 80 chars before the
* 1st star symbol are truncated.

1 * grammatical gender: 1 = male, 2 = female, 3 = neutral
Ο * article (1st person, singular)
ΑΣΒΟΣ * name in singular
ΑΣΒΟ * name in singlular, accusative case
ΑΣΒΟΙ * name in plural


* Book-Info Part
* ------------------------------------------------------
* Empty lines & lines STARTING with blanks or with the STAR
* symbol are IGNORED. To force one or more empty lines on
* teh output, use one or more # (usually at the start or
* the end of paragraphs). If you put them alone in a line
* they will produce as many empty lines as their count + 1.
*
* On output, a tab charcater will be added at the start of
* every line. So keep their length less than 64,65 characters,
* otherwise the they will not look nice on the screen (they
* will wrap around).
*
* Here is the text that will appear on the output...

Ο ασβός είναι θηλαστικό ζώο, της οικογενείας των Μουστελιδών
(Meles meles). Συναντάται στην Ευρώπη και στη Β. Ασία, διάγοντας
μοναχικό βίο, σαν ερημίτης. Στη χώρα μας ζεί το μεγαλύτερο είδος
της οικογένειας.#

Είναι νυχτόβιο ζώο, ζυγίζει περίπου 15 κιλά και μοιάζει πολύ με
μεγάλο σκαντζόχοιρο ή μικρή αρκούδα. Χαρακτηριστικό του γνώρισμα
είναι η διχρωμία σκούρου καφέ (ή μαύρου) με λευκό, που ξεκινά από
το άκρο του ρύγχους και καταλήγει πίσω από τα αυτιά.#

Την ημέρα κρύβεται στη φωλιά του, που είναι στρωμένη με άχυρο και
πάντα περιποιημένη. Είναι επίσης δαιδαλώδης, με εξόδους διαφυγής
σε περίπτωση κινδύνου. Συνδέεται ισόβια με τον σύντροφο του, με
τον οποίο μοιράζεται τη φωλιά του, κι έχουν αναφερθεί περιστατικά
με ασβούς να θάβουν νεκρά μέλη της οικογένειάς τους.#

Τρέφεται κυρίως με έντομα, σκουλήκια, σαλιγκάρια, ενώ του αρέσει
πολύ και το μέλι. Δεν περιφρονεί επίσης ρίζες, καρπούς, αρουραιους,
λαγούς, πέρδικες, βατράχια, ακόμα και φίδια. Χρησιμοποιεί ως μέσο
άμυνας την αποβολή δύσοσμων εκκρίσεων που απομακρύνουν τον εχθρό.

Προφανώς για κάθε γλώσσα τα ζώο έχει διαφορετικό language αρχείο.

Το ζουμί είναι πως όποιος θέλει να προσθέσει ένα νέο ζώο, π.χ. μια ζέβρα, αρκεί να προσθέσει τη γραμμή

Κώδικας: Επιλογή όλων
10 zebra

στο τέλος του αρχείου tanimal.idx και να φτιάξει 2 αρχεία zebra.dat και zebra.lng και καθάρισε. Μέσα στο πρόγραμμά του θα μπορεί να δημιουργεί και να διαχειρίζεται ζέβρες...

Μορφοποιημένος Κώδικας: Επιλογή όλων
TAnimal *zebra = tanimal_new( 10 );
...
tanimal_randomize_attributes( zebra );
...
tanimal_free( zebra );

Ήδη έχω φτιάξει αυτόνομα και λειτουργούν οι parsers των παραπάνω αρχείων, οι οποίοι τα καθαρίζουν από σχόλια και κενές γραμμές και αναθέτουν τις αναγραφόμενες τιμές στα αντίστοιχα πεδία του ζώου.

Πρέπει να ενσωματωθούν στον κώδικα της βιβλιοθήκης και φυσικά να προσαρμοστούν ανάλογα οι υπάρχουσες συναρτήσεις. Επίσης πρέπει από τώρα που είναι νωρίς να προσθέσω κι άλλα πεδία στο struct του ζώου (π.χ. χρώμα, δύναμη, αντοχή, κλπ) που θα χρειαστούν αναπροσαρμογή τόσο των συναρτήσεων όσο και των αρχείων. Δηλαδή με άλλα λόγια, πρέπει να αναδιοργανωθεί και πάλι σχεδόν ριζικά όλος ο κώδικας του χαμηλότερου layer, αφήνοντας ανέπαφο το από πάνω layer (το τεκμηριωμένο ;) )

Πέρα από τη χαμαλοδουλειά, υπάρχουν κι άλλα θέματα που θα με πάρουν χρόνο. Για παράδειγμα, όταν υπήρχε προκαθορισμένος αριθμός ζώων μέσα στον κώδικα, η υλοποίηση της υψηλού-επιπέδου συνάρτησης δημιουργίας τυχαίου ζώου ήταν ένα απλό...

Μορφοποιημένος Κώδικας: Επιλογή όλων
TAnimal *tanimal_new_random( void )    /* high-level function */
{
return self_new( rand() % MAX_TANIMALS ); /* call low-level function */
}
γιατί το MAX_TANIMALS ήταν προκαθορισμένο, γνωστό και άμεσα διαθέσιμο.

Τώρα πρέπει να ανοιχτεί το αρχείο tanimal.idx, να αφαιρεθούν σχόλια και κενές γραμμές και να μετρηθούν όσες γραμμές απομείνουν. Ένα είναι αυτό, το άλλο είναι να αποφασίσω πως θα διαχειρίζομαι το υπολογισμένο πλήθος των ζώων. Π.χ. μια πιθανότητα είναι να ακολουθείται η παραπάνω διαδικασία κάθε φορά που καλείται η συνάρτηση tanimal_New() και όποια άλλη παρεμφερής. Μια άλλη πιθανότητα είναι η παραπάνω διαδικασία να γίνεται μονάχα στη 1η κλήση οποιασδήποτε συνάρτησης δημιουργίας νέου ζώου και το αποτέλεσμα να αποθηκεύεται σε μια εσωτερική καθολική μεταβλητή. Οπότε όταν ξανα-χρειαστεί το μέγιστο πλήθος να μην ανοίγει το αρχείο tanimal.idx, αλλά να χρησιμοποιείται η εσωτερική καθολική μεταβλητή. Αυτό σίγουρα είναι ταχύτερο, αλλά χρειάζεται έξτρα κώδικα για να διασφαλιστεί πως θα είναι thread-friendly (μπελάς). Μια άλλη πιθανότητα είναι να υποχρεώνω τον χρήστη να περνάει το MAX_TANIMALS ως παράμετρο:

Μορφοποιημένος Κώδικας: Επιλογή όλων
TAnimal *tanimal_new_random( int maxanimals );
και να του παρέχω μια συνάρτηση που θα διαβάζει το tanimal.idx και θα επιστρέφει το μέγιστο πλήθος ζώων. Π.χ.

Μορφοποιημένος Κώδικας: Επιλογή όλων
int tanimal_maxcount( void )
οπότε πετάω το μπαλάκι σε εκείνον για το πως θα τα συνδυάσει. Να μπορεί δηλαδή είτε να διαβάσει το αρχείο μια μόνο φορά αποθηκεύοντας την τιμή επιστροφής της παραπάνω συνάρτησης σε μια δικιά του μεταβλητή και να την χρησιμοποιεί κατόπιν όπου θέλει...

Μορφοποιημένος Κώδικας: Επιλογή όλων
int maxanimals = tanimal_maxcount();
TAnimal *randanimal = tanimal_new_random( maxanimals );

ή να το κάνει δυναμικά κάθε φορά...

Μορφοποιημένος Κώδικας: Επιλογή όλων
TAnimal *randanimal = tanimal_new_random(  tanimal_maxcount() );

ή
Μορφοποιημένος Κώδικας: Επιλογή όλων
TAnimal *randanimal = tanimal_new( rand() % tanimal_maxcount() );

Υπάρχουν πολλά τέτοια, στα οποία πρέπει να σταθμίσω υπερ & κατά πριν αποφασίσω πως θα τα υλοποιήσω.

Ένα άλλο παράδειγμα είναι το κείμενο book-info του κάθε ζώου. Μέχρι τώρα το αποθήκευα μέσα στο struct του κάθε ζώο, σε ξεχωριστό πεδίο: book. Τώρα το άλλαξα και όταν ο χρήστης ζητήσει: tanimal_open_media_book( animal ); ανοίγω το language αρχείο του ζώου, το καθαρίζω από σχόλια & κενές γραμμές, κάνω σκιπ τις πρώτες 5 γραμμές (στο καθαρό αρχείο) και τυπώνω όλες τις υπόλοιπες. Με λίγα λόγια, δεν κουβαλάω το κείμενο του κάθε ζώου στο struct του (κέρδος σε μνήμη), κάνω όμως parse το αρχείο κάθε φορά που ζητηθεί τύπωμα (κόστος σε ταχύτητα).

Χρονοβόρο project, αλλά αν πετύχει μπορεί να αποδειχτεί χρήσιμο, αφού θα μπορεί να χρησιμοποιηθεί σε ποικιλόμορφες εφαρμογές, διατηρώντας κοινό interface (σκέφτομαι να προσθέσω και υποστήριξη λιστών από ζώα στη βιβλιοθήκη... δηλαδή, αφηρημένες λίστες με στανταρισμένο εξωτερικό interface αλλά που εσωτερικά μπορεί να υλοποιείται είτε με πίνακες, είτε λίστες, είτε όπως αλλιώς).