Ingen beskrivning
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

randomem.py 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #-*- coding: utf-8 -*-
  2. ## @package EditorialModel.randomem
  3. #
  4. # Provide methods for random EM generation
  5. import random
  6. from EditorialModel.backend.dummy_backend import EmBackendDummy
  7. from EditorialModel.model import Model
  8. from EditorialModel.fieldgroups import EmFieldGroup
  9. from EditorialModel.fields import EmField
  10. from EditorialModel.types import EmType
  11. from EditorialModel.classtypes import EmClassType
  12. from Lodel.utils.mlstring import MlString
  13. class RandomEm(object):
  14. ## @brief Instanciate a class allowing to generate random EM
  15. # @see RandomEm::random_em()
  16. def __init__(self, backend=None, **kwargs):
  17. self.backend = backend
  18. self.kwargs = kwargs
  19. ## @brief Return a random EM
  20. # @return A random EM
  21. def gen(self):
  22. return self.random_em(self.backend, **self.kwargs)
  23. @classmethod
  24. ## @brief Generate a random editorial model
  25. #
  26. # The random generator can be tuned with integer parameters
  27. # that represent probability or maximum numbers of items.
  28. # The probability (chances) works like 1/x chances to append
  29. # with x the tunable parameter
  30. # Tunable generator parameters :
  31. # - classtype : Chances for a classtype to be empty (default 0)
  32. # - nclass : Maximum number of classes per classtypes (default 5)
  33. # - nofg : Chances for a classe to have no fieldgroup associated to it (default 10)
  34. # - notype : Chances for a classe to have no type associated to it (default 5)
  35. # - seltype : Chances for a type to select an optionnal field (default 2)
  36. # - ntypesuperiors : Chances for a type to link with a superiors (default 3)
  37. # - nofields : Chances for a fieldgroup to be empty (default 10)
  38. # - nfields : Maximum number of field per fieldgroups (default 8)
  39. # - rfields : Maximum number of relation_to_type attributes fields (default 5)
  40. # - optfield : Chances for a field to be optionnal (default 2)
  41. # @param backend : A backend to use with the new EM
  42. # @param **kwargs dict : Provide tunable generation parameter
  43. # @return A randomly generate EM
  44. def random_em(cls, backend=None, **kwargs):
  45. ed_mod = Model(EmBackendDummy if backend is None else backend)
  46. chances = {
  47. 'classtype': 0, # a class in classtype
  48. 'nclass': 5, # max number of classes per classtype
  49. 'nofg': 10, # no fieldgroup in a class
  50. 'nfg': 5, # max number of fieldgroups per classes
  51. 'notype': 10, # no types in a class
  52. 'ntype': 8, # max number of types in a class
  53. 'seltype': 2, # chances to select an optional field
  54. 'ntypesuperiors': 2, # chances to link with a superior
  55. 'nofields': 10, # no fields in a fieldgroup
  56. 'nfields': 8, # max number of fields per fieldgroups
  57. 'rfields': 5, # max number of attributes relation fields
  58. 'optfield': 2, # chances to be optionnal
  59. }
  60. for name, value in kwargs.items():
  61. if name not in chances:
  62. #warning
  63. pass
  64. else:
  65. chances[name] = value
  66. #classes creation
  67. for classtype in EmClassType.getall():
  68. if random.randint(0, chances['classtype']) == 0:
  69. for _ in range(random.randint(1, chances['nclass'])):
  70. cdats = cls._rnd_component_datas()
  71. cdats['classtype'] = classtype['name']
  72. ed_mod.create_component('EmClass', cdats)
  73. for emclass in ed_mod.classes():
  74. #fieldgroups creation
  75. if random.randint(0, chances['nofg']) != 0:
  76. for _ in range(random.randint(1, chances['nfg'])):
  77. fgdats = cls._rnd_component_datas()
  78. fgdats['class_id'] = emclass.uid
  79. ed_mod.create_component('EmFieldGroup', fgdats)
  80. #types creation
  81. if random.randint(0, chances['notype']) != 0:
  82. for _ in range(random.randint(1, chances['ntype'])):
  83. tdats = cls._rnd_component_datas()
  84. tdats['class_id'] = emclass.uid
  85. ed_mod.create_component('EmType', tdats)
  86. #random type hierarchy
  87. for emtype in ed_mod.components(EmType):
  88. possible = emtype.possible_superiors()
  89. for nat in possible:
  90. if len(possible[nat]) > 0 and random.randint(0, chances['ntypesuperiors']) == 0:
  91. random.shuffle(possible[nat])
  92. for i in range(random.randint(1, len(possible[nat]))):
  93. emtype.add_superior(possible[nat][i], nat)
  94. #fields creation
  95. ft_l = EmField.fieldtypes_list()
  96. for emfg in ed_mod.components(EmFieldGroup):
  97. if random.randint(0, chances['nofields']) != 0:
  98. for _ in range(random.randint(1, chances['nfields'])):
  99. field_type = ft_l[random.randint(0, len(ft_l) - 1)]
  100. fdats = cls._rnd_component_datas()
  101. fdats['fieldtype'] = field_type
  102. fdats['fieldgroup_id'] = emfg.uid
  103. if field_type == 'rel2type':
  104. emtypes = ed_mod.components(EmType)
  105. fdats['rel_to_type_id'] = emtypes[random.randint(0, len(emtypes) - 1)].uid
  106. if random.randint(0, chances['optfield']) == 0:
  107. fdats['optional'] = True
  108. ed_mod.create_component('EmField', fdats)
  109. #relationnal fiels creation
  110. ft_l = [field_type for field_type in EmField.fieldtypes_list() if field_type != 'rel2type']
  111. for emrelf in [f for f in ed_mod.components(EmField) if f.ftype == 'rel2type']:
  112. for _ in range(0, chances['rfields']):
  113. field_type = ft_l[random.randint(0, len(ft_l) - 1)]
  114. fdats = cls._rnd_component_datas()
  115. fdats['fieldtype'] = field_type
  116. fdats['fieldgroup_id'] = emrelf.fieldgroup_id
  117. if random.randint(0, chances['optfield']) == 0:
  118. fdats['optional'] = True
  119. ed_mod.create_component('EmField', fdats)
  120. #selection optionnal fields
  121. for emtype in ed_mod.components(EmType):
  122. selectable = [field for fieldgroup in emtype.fieldgroups() for field in fieldgroup.fields() if field.optional]
  123. for field in selectable:
  124. if random.randint(0, chances['seltype']) == 0:
  125. emtype.select_field(field)
  126. return ed_mod
  127. @staticmethod
  128. ## @brief Generate a random string
  129. # @warning dirty cache trick with globals()
  130. # @return a randomly selected string
  131. def _rnd_str(words_src='/usr/share/dict/words'):
  132. if '_words' not in globals() or globals()['_words_fname'] != words_src:
  133. globals()['_words_fname'] = words_src
  134. with open(words_src, 'r') as fpw:
  135. globals()['_words'] = [l.strip() for l in fpw]
  136. words = globals()['_words']
  137. return words[random.randint(0, len(words) - 1)]
  138. @classmethod
  139. ## @brief Generate a random MlString
  140. # @param nlng : Number of langs in the MlString
  141. # @return a random MlString with nlng translations
  142. # @todo use a dict to generated langages
  143. def _rnd_mlstr(cls, nlng):
  144. ret = MlString()
  145. for _ in range(nlng):
  146. ret.set(cls._rnd_str(), cls._rnd_str())
  147. return ret
  148. @classmethod
  149. ## @brief returns randomly generated datas for an EmComponent
  150. # @return a dict with name, string and help_text
  151. def _rnd_component_datas(cls):
  152. mlstr_nlang = 2
  153. ret = dict()
  154. ret['name'] = cls._rnd_str()
  155. ret['string'] = cls._rnd_mlstr(mlstr_nlang)
  156. ret['help_text'] = cls._rnd_mlstr(mlstr_nlang)
  157. return ret