No Description
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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. # @param cls
  44. # @return A randomly generate EM
  45. def random_em(cls, backend=None, **kwargs):
  46. ed_mod = Model(EmBackendDummy if backend is None else backend)
  47. chances = {
  48. 'classtype': 0, # a class in classtype
  49. 'nclass': 5, # max number of classes per classtype
  50. 'nofg': 10, # no fieldgroup in a class
  51. 'nfg': 5, # max number of fieldgroups per classes
  52. 'notype': 10, # no types in a class
  53. 'ntype': 8, # max number of types in a class
  54. 'seltype': 2, # chances to select an optional field
  55. 'ntypesuperiors': 2, # chances to link with a superior
  56. 'nofields': 10, # no fields in a fieldgroup
  57. 'nfields': 8, # max number of fields per fieldgroups
  58. 'rfields': 5, # max number of attributes relation fields
  59. 'optfield': 2, # chances to be optionnal
  60. }
  61. for name, value in kwargs.items():
  62. if name not in chances:
  63. #warning
  64. pass
  65. else:
  66. chances[name] = value
  67. #classes creation
  68. for classtype in EmClassType.getall():
  69. if random.randint(0, chances['classtype']) == 0:
  70. for _ in range(random.randint(1, chances['nclass'])):
  71. cdats = cls._rnd_component_datas()
  72. cdats['classtype'] = classtype['name']
  73. ed_mod.create_component('EmClass', cdats)
  74. for emclass in ed_mod.classes():
  75. #fieldgroups creation
  76. if random.randint(0, chances['nofg']) != 0:
  77. for _ in range(random.randint(1, chances['nfg'])):
  78. fgdats = cls._rnd_component_datas()
  79. fgdats['class_id'] = emclass.uid
  80. ed_mod.create_component('EmFieldGroup', fgdats)
  81. #types creation
  82. if random.randint(0, chances['notype']) != 0:
  83. for _ in range(random.randint(1, chances['ntype'])):
  84. tdats = cls._rnd_component_datas()
  85. tdats['class_id'] = emclass.uid
  86. ed_mod.create_component('EmType', tdats)
  87. #random type hierarchy
  88. for emtype in ed_mod.components(EmType):
  89. possible = emtype.possible_superiors()
  90. for nat in possible:
  91. if len(possible[nat]) > 0 and random.randint(0, chances['ntypesuperiors']) == 0:
  92. random.shuffle(possible[nat])
  93. for i in range(random.randint(1, len(possible[nat]))):
  94. emtype.add_superior(possible[nat][i], nat)
  95. #fields creation
  96. ft_l = EmField.fieldtypes_list()
  97. for emfg in ed_mod.components(EmFieldGroup):
  98. if random.randint(0, chances['nofields']) != 0:
  99. for _ in range(random.randint(1, chances['nfields'])):
  100. field_type = ft_l[random.randint(0, len(ft_l) - 1)]
  101. fdats = cls._rnd_component_datas()
  102. fdats['fieldtype'] = field_type
  103. fdats['fieldgroup_id'] = emfg.uid
  104. if field_type == 'rel2type':
  105. emtypes = ed_mod.components(EmType)
  106. fdats['rel_to_type_id'] = emtypes[random.randint(0, len(emtypes) - 1)].uid
  107. if random.randint(0, chances['optfield']) == 0:
  108. fdats['optional'] = True
  109. ed_mod.create_component('EmField', fdats)
  110. #relationnal fiels creation
  111. ft_l = [field_type for field_type in EmField.fieldtypes_list() if field_type != 'rel2type']
  112. for emrelf in [f for f in ed_mod.components(EmField) if f.ftype == 'rel2type']:
  113. for _ in range(0, chances['rfields']):
  114. field_type = ft_l[random.randint(0, len(ft_l) - 1)]
  115. fdats = cls._rnd_component_datas()
  116. fdats['fieldtype'] = field_type
  117. fdats['fieldgroup_id'] = emrelf.fieldgroup_id
  118. if random.randint(0, chances['optfield']) == 0:
  119. fdats['optional'] = True
  120. ed_mod.create_component('EmField', fdats)
  121. #selection optionnal fields
  122. for emtype in ed_mod.components(EmType):
  123. selectable = [field for fieldgroup in emtype.fieldgroups() for field in fieldgroup.fields() if field.optional]
  124. for field in selectable:
  125. if random.randint(0, chances['seltype']) == 0:
  126. emtype.select_field(field)
  127. return ed_mod
  128. @staticmethod
  129. ## @brief Generate a random string
  130. # @warning dirty cache trick with globals()
  131. # @return a randomly selected string
  132. def _rnd_str(words_src='/usr/share/dict/words'):
  133. if '_words' not in globals() or globals()['_words_fname'] != words_src:
  134. globals()['_words_fname'] = words_src
  135. with open(words_src, 'r') as fpw:
  136. globals()['_words'] = [l.strip() for l in fpw]
  137. words = globals()['_words']
  138. return words[random.randint(0, len(words) - 1)]
  139. @classmethod
  140. ## @brief Generate a random MlString
  141. # @param nlng : Number of langs in the MlString
  142. # @return a random MlString with nlng translations
  143. # @todo use a dict to generated langages
  144. def _rnd_mlstr(cls, nlng):
  145. ret = MlString()
  146. for _ in range(nlng):
  147. ret.set(cls._rnd_str(), cls._rnd_str())
  148. return ret
  149. @classmethod
  150. ## @brief returns randomly generated datas for an EmComponent
  151. # @return a dict with name, string and help_text
  152. def _rnd_component_datas(cls):
  153. mlstr_nlang = 2
  154. ret = dict()
  155. ret['name'] = cls._rnd_str()
  156. ret['string'] = cls._rnd_mlstr(mlstr_nlang)
  157. ret['help_text'] = cls._rnd_mlstr(mlstr_nlang)
  158. return ret