Hello, I have made an experiment to show how LISFS could be used to navigate and build classification. For this, I created a file hierarchy corresponding to the current classification in the demo server[1] over a LISFS real file system[2].
==AN EXAMPLE OF EXPLORATION== So at LISFS root, I can do a 'ls': [EMAIL PROTECTED]:~/pub/lisfs/mounted$ ls -F 00-pool/ propagande/ question 200/ admin/ question 104/ question 202/ aéroports/ question 108/ question 204/ âge limite/ question 113/ question 205/ agriculture/ question 117/ question 206/ alimentation/ question 118/ question 207/ anglais/ question 119/ question 208/ anglais-français/ question 129/ question 209/ antonyme/ question 130/ question 21/ armée/ question 131/ question 210/ armes/ question 132/ question 211/ association/ question 133/ question 212/ automobile/ question 134/ question 213/ [...output cut...] I can navigate into a tag, to see question and other tags attached to it: [EMAIL PROTECTED]:~/pub/lisfs/mounted$ cd Rennes/ [EMAIL PROTECTED]:~/pub/lisfs/mounted/Rennes$ ls -F association/ expérience démocratique/ demexp/ financement/ Doit-on créer une piste cyclable à contre-sens quai de la Prévalaye ? financement demexp/ élection/ question 179/ esthétique/ You can see two things: 1. question "Doit-on ... Prévalaye ?" as only tag "Rennes", so no further exploration is possible and the question is presented as a file (see below); 2. other sub-directories are shown, that show additional tags to make a research. You can see the content of the question "Doit-on ... Prévalaye ?": [EMAIL PROTECTED]:~/pub/lisfs/mounted/Rennes$ cat Doit-on\ créer\ une\ piste\ cyclable\ à\ contre-sens\ quai\ de\ la\ Prévalaye\ \? 46: Doit-on créer une piste cyclable à contre-sens quai de la Prévalaye ? Tags:['Rennes'] Responses: - Question rejected - non - oui, en supprimant le trotoire qui longe le quai - oui, en supprimant les places de stationnement - Oui, à condition que l'expérience démocratique détienne la majorité du conseil municipal de Rennes et en réduisant l'espace de circulation voitures But you can also refine your search by 'cd' and 'ls' in the file hierarchy: [EMAIL PROTECTED]:~/pub/lisfs/mounted/Rennes$ cd expérience\ démocratique/ [EMAIL PROTECTED]:~/pub/lisfs/mounted/Rennes/expérience démocratique$ ls -F association/ demexp/ élection/ financement/ financement demexp/ [EMAIL PROTECTED]:~/pub/lisfs/mounted/Rennes/expérience démocratique$ cd demexp/ [EMAIL PROTECTED]:~/pub/lisfs/mounted/Rennes/expérience démocratique/demexp$ ls -F Dans quelle banque l'association de financement de demexp doit-elle ouvrir son compte ? And we can show the content of the only question: [EMAIL PROTECTED]:~/pub/lisfs/mounted/Rennes/expérience démocratique/demexp$ cat Dans\ quelle\ banque\ l\ 'association\ de\ financement\ de\ demexp\ doit-elle\ ouvrir\ son\ compte\ \? 50: Dans quelle banque l'association de financement de demexp doit-elle ouvrir son compte ? Tags:['exp\xc3\xa9rience d\xc3\xa9mocratique', 'financement', 'financement demexp', 'demexp', 'association', 'Rennes'] Responses: - Question rejected - Le Crédit mutuel de Bretagne - La Nef (à l'agence du Crédit coopératif de Rennes) - Le Crédit coopératif (agence de Rennes) - La poste (ils exigent que ce soit dans le bureau de poste du siège social de l'association) - 2 - Le Crédit Agricole You can notice an important property of LISFS: question 50 has 6 tags but only 3 are needed to reach the question. For example, tag 'financement' is no longer discriminatory as soon as we have entered the "Rennes/expérience démocratique/demexp" directory, so it is not shown as sub-directory. LISFS theory and code allow also to modify the hierachy dynamically, while searching. This is quite powerful: you can navigate, find that the classification needs some modification and modify it lively! Moreover, typed attributes can be attached. For example question identifiers can be attached to a question and one could do: cd qid:>10/qid:<20/ # to see questions #11 to #19 LISFS also support classification hierarchy. So we could have a tag "Cities" that contains "Rennes", "Bruxelles", ... At the upper level, only Cities/ directory would be displayed. ==REMAINING WORK== This is just an dummy example, the real server classification cannot be explored and modified through this system. And some details need to be worked out, like not displaying the "question NNN" tags. But all the OCaml code is available, freely (GPL license), so this is "just" a question of writing proper gluing code. ;) What do you think of it? Do you find the system appealing or does it seems to you too much complicated? Regarding architecture, I'm wondering if putting such a system into the server couldn't be very useful: every client (even Python scripts! ;) could use this system. Best wishes, d. PS: "[technology preview]": yes, I'm reading for the marketing department. :) Footnotes: [1] I have used a Python script (well, rather a hack) using Thomas' pydemexp toolkit for this. It's very useful Thomas! Here is the used pydemexp script:
#!/usr/bin/python import sys import socket import DemexpRpc import string import os # for debug #count_max=2 count_max=10000 def check_return_code(c): if c != DemexpRpc.const.rt_ok: print "Error: " + DemexpRpc.const.return_code_t[c] \ + " (" + str(c) + ")" sys.exit (1) # Check arguments if len(sys.argv) != 1: print "Usage: make-directories.py" sys.exit (1) # Connect to the server try: c = DemexpRpc.client.Demexp.V1("tuxinette.linux-france.org",50000) except socket.error: print "Connexion failed to tuxinette.linux-france.org:50000" sys.exit (1) # Login on the server login_ret = c.login(DemexpRpc.const.PROTOCOL_VERSION, "demo", "demo") # Check the protocol version returned by the server to see if it's the # same as the one we implement if login_ret.server_protocol_version != DemexpRpc.const.PROTOCOL_VERSION: print "Server has a different protocol version" sys.exit (1) # Check that login was successful check_return_code(login_ret.login_return_code) cookie = login_ret.login_cookie # Get the maximum tag ID ret = c.max_tag_id(cookie) check_return_code(ret.max_tag_id_rc) # Get a hash of tags tag_labels = {} for i in range (0, min(count_max, ret.max_tag_id + 1)): ret = c.tag_info(cookie, i, 1) check_return_code(ret.tag_info_rc) tag_labels[i] = ret.tag_info[0].a_tag_label print str(i) + ". " + tag_labels[i] try: os.mkdir(tag_labels[i]) except OSError: pass # Get the maximum question ID ret = c.max_question_id(cookie) check_return_code(ret.max_question_id_rc) max_question_id = ret.max_question_id # Get the tags of a question tags_of_question = {} for i in range (0, min(count_max, max_question_id + 1)): ret = c.get_question_tags(cookie, i) tags_of_question[i] = ret print ("Tags question %d: " % i) + repr(tags_of_question[i]) # List the questions and their tags for i in range (0, min(count_max, max_question_id + 1)): ret = c.question_info (cookie, i, 1) check_return_code(ret.question_info_rc) question = ret.question_info[0] #print str(i) + ". " + question.q_desc question_tags = [] for t_id in tags_of_question[i]: question_tags.append(tag_labels[t_id]) #print question_tags path = string.join(question_tags, "/") + "/" + question.q_desc print str(i) + ": " + path try: f = open(path,"w") f.write(str(i) + ": " + question.q_desc + "\n") f.write("Tags:" + repr(question_tags) + "\n") f.write("Responses:\n") for response in question.q_info_responses: f.write(" - " + response.r_info_desc + "\n") f.close() except (OSError, IOError): pass # Disconnect c.goodbye(cookie) sys.exit(0)
[2] I can provide LISFS code if needed. -- pub 1024D/A3AD7A2A 2004-10-03 David MENTRE <[EMAIL PROTECTED]> 5996 CC46 4612 9CA4 3562 D7AC 6C67 9E96 A3AD 7A2A
_______________________________________________ Demexp-dev mailing list Demexp-dev@nongnu.org http://lists.nongnu.org/mailman/listinfo/demexp-dev