#wip: Doing AnP Framwork Upgrade Scripts?
This commit is contained in:
parent
f1338e0704
commit
15ba494ef8
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,4 +2,5 @@
|
|||||||
/Public/data
|
/Public/data
|
||||||
*.[Ss]ecret.*
|
*.[Ss]ecret.*
|
||||||
*.[Ss]ecrets.*
|
*.[Ss]ecrets.*
|
||||||
__pycache__
|
__pycache__
|
||||||
|
.sass-cache
|
||||||
3
JSON/I18N/OpoTests.i18n.espanol.json
Normal file
3
JSON/I18N/OpoTests.i18n.espanol.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"espanol" : {}
|
||||||
|
}
|
||||||
4
JSON/OpoTests.routes.json
Normal file
4
JSON/OpoTests.routes.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
"get:/ping ping@test",
|
||||||
|
"get:/ /Public"
|
||||||
|
]
|
||||||
13
JSON/OpoTests.settings.json
Normal file
13
JSON/OpoTests.settings.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"default_settings_files": ["/JSON/OpoTests.settings.json"],
|
||||||
|
"default_secrets_files": ["/JSON/OpoTests.secrets.json"],
|
||||||
|
"default_i18n_files": [
|
||||||
|
"/JSON/I18N/OpoTests.i18n.espanol.json",
|
||||||
|
"/JSON/I18N/OpoTests.i18n.galego.json",
|
||||||
|
"/JSON/I18N/OpoTests.i18n.english.json",
|
||||||
|
"/JSON/I18N/OpoTests.i18n.nihongo.json",
|
||||||
|
"/JSON/I18N/OpoTests.i18n.russkyi.json"
|
||||||
|
],
|
||||||
|
"default_language": "es",
|
||||||
|
"default_routes_files" : ["/JSON/OpoTests.routes.json"]
|
||||||
|
}
|
||||||
@ -71,8 +71,12 @@ export const OpoTests = (function(){
|
|||||||
/** @type {OpoTests} */
|
/** @type {OpoTests} */
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
|
/** @type {Array.<Object.<string, any>>} */
|
||||||
this.database = [];
|
this.database = [];
|
||||||
|
/** @type {Object.<string, string|Array.<string|number|Array.<any|null>>>} */
|
||||||
this.variables = {};
|
this.variables = {};
|
||||||
|
/** @type {Object.<string, string|Array.<string|number|Array.<any|null>>>} */
|
||||||
|
this.group_variables = {};
|
||||||
|
|
||||||
/** @type {SettingsManager} */
|
/** @type {SettingsManager} */
|
||||||
this.settings = new SettingsManager(self, inputs);
|
this.settings = new SettingsManager(self, inputs);
|
||||||
@ -117,7 +121,7 @@ export const OpoTests = (function(){
|
|||||||
});
|
});
|
||||||
}, next_callback);
|
}, next_callback);
|
||||||
}, () => {
|
}, () => {
|
||||||
console.log(["database", self.database, self.variables]);
|
console.log(["database", self.database, self.variables, self.group_variables]);
|
||||||
self.main_form.build();
|
self.main_form.build();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -231,10 +235,11 @@ export const OpoTests = (function(){
|
|||||||
* @returns {void}
|
* @returns {void}
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
const add_to_variables = set => {
|
const add_to_variables = (variables, set, group = null) => {
|
||||||
|
group && (variables = variables[group] || (variables[group] = {}));
|
||||||
Check.is_dictionary(set) &&
|
Check.is_dictionary(set) &&
|
||||||
Object.entries(set).forEach(([key, value]) => {
|
Object.entries(set).forEach(([key, value]) => {
|
||||||
self.variables[key] = value;
|
variables[key] = value;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -251,10 +256,15 @@ export const OpoTests = (function(){
|
|||||||
try{
|
try{
|
||||||
self.database.push(...JSON.parse(responseText).map(item => {
|
self.database.push(...JSON.parse(responseText).map(item => {
|
||||||
|
|
||||||
add_to_variables(item.variables);
|
/** @type {string} */
|
||||||
|
const group = item.group || Utils.to_snake_case(item.origin + "_" + item.title);
|
||||||
|
|
||||||
|
add_to_variables(self.variables, item.variables);
|
||||||
|
item.group_variables && add_to_variables(self.group_variables, item.group_variables, item.group || (item.group = group));
|
||||||
item.queries = (item.queries || []).filter(subitem => {
|
item.queries = (item.queries || []).filter(subitem => {
|
||||||
if(Check.is_dictionary(subitem)){
|
if(Check.is_dictionary(subitem)){
|
||||||
add_to_variables(subitem.variables);
|
add_to_variables(self.variables, subitem.variables);
|
||||||
|
subitem.group_variables && add_to_variables(self.group_variables, item.group_variables, item.group || (item.group = group));
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -42,18 +42,20 @@ export const CapitalizeFormat = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!(string|Array.<any|null>)} inputs
|
* @param {!(string|Array.<any|null>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
* @param {!Array.<string>} [fragments = []]
|
* @param {!Array.<string>} [fragments = []]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.get = (inputs, shared = {}, fragments = []) => format.execute(
|
this.get = ([i, j], inputs, shared = {}, fragments = []) => format.execute([i, j],
|
||||||
Check.is_string(inputs) ? inputs :
|
Check.is_string(inputs) ? inputs :
|
||||||
Check.is_string(inputs[0]) ? inputs[0] :
|
Check.is_string(inputs[0]) ? inputs[0] :
|
||||||
"", shared, fragments).replace(/^./, character => character.toUpperCase());
|
"", shared, fragments).replace(/^./, character => character.toUpperCase());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!(string|Array.<string>)} inputs
|
* @param {!(string|Array.<string>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -61,7 +63,7 @@ export const CapitalizeFormat = (function(){
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.check = (string, inputs, shared = {}, fragments = []) => {
|
this.check = ([i, j], string, inputs, shared = {}, fragments = []) => {
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
const substring = format.set_fragments_level((
|
const substring = format.set_fragments_level((
|
||||||
@ -70,7 +72,7 @@ export const CapitalizeFormat = (function(){
|
|||||||
""), fragments);
|
""), fragments);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
/\{[^\{\}]+\}/.test(substring) ? format.get_check_length(string, [substring], shared, fragments, false) :
|
/\{[^\{\}]+\}/.test(substring) ? format.get_check_length([i, j], string, [substring], shared, fragments, false) :
|
||||||
FormatModule.prepare_result(string, substring, shared));
|
FormatModule.prepare_result(string, substring, shared));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -37,22 +37,23 @@ export const MixFormat = (function(){
|
|||||||
const constructor = () => {
|
const constructor = () => {
|
||||||
format.modes.mix = self.get;
|
format.modes.mix = self.get;
|
||||||
format.checks.mix = self.check;
|
format.checks.mix = self.check;
|
||||||
format.modes.Mix = (inputs, shared, fragments) => self.get(inputs, {
|
format.modes.Mix = ([i, j], inputs, shared, fragments) => self.get([i, j], inputs, {
|
||||||
...shared, capitalized : true
|
...shared, capitalized : true
|
||||||
}, fragments);
|
}, fragments);
|
||||||
format.checks.Mix = (string, inputs, shared, fragments) => self.check(string, inputs, {
|
format.checks.Mix = ([i, j], string, inputs, shared, fragments) => self.check([i, j], string, inputs, {
|
||||||
...shared, capitalized : true
|
...shared, capitalized : true
|
||||||
}, fragments);
|
}, fragments);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!(string|Array.<any|null>)} inputs
|
* @param {!(string|Array.<any|null>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
* @param {!Array.<string>} [fragments = []]
|
* @param {!Array.<string>} [fragments = []]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.get = (inputs, shared = {}, fragments = []) => {
|
this.get = ([i, j], inputs, shared = {}, fragments = []) => {
|
||||||
|
|
||||||
/** @type {[string, Array.<string>]} */
|
/** @type {[string, Array.<string>]} */
|
||||||
const [separator, original_items] = (
|
const [separator, original_items] = (
|
||||||
@ -62,14 +63,14 @@ export const MixFormat = (function(){
|
|||||||
Check.is_array(inputs) ? inputs :
|
Check.is_array(inputs) ? inputs :
|
||||||
[]),
|
[]),
|
||||||
/** @type {Array.<string>} */
|
/** @type {Array.<string>} */
|
||||||
items = [...original_items];
|
items = format.get_list([i, j], [...original_items]);
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
let l = items.length,
|
let l = items.length,
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
results;
|
results;
|
||||||
|
|
||||||
Utils.randomize_array(items);
|
Utils.randomize_array(items);
|
||||||
results = format.execute(
|
results = format.execute([i, j],
|
||||||
l < 2 ? items.join("") :
|
l < 2 ? items.join("") :
|
||||||
items.slice(0, l - 1).join(", ") + (
|
items.slice(0, l - 1).join(", ") + (
|
||||||
!separator ? " " :
|
!separator ? " " :
|
||||||
@ -80,6 +81,7 @@ export const MixFormat = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!(string|Array.<string>)} inputs
|
* @param {!(string|Array.<string>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -87,19 +89,21 @@ export const MixFormat = (function(){
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.check = (string, inputs, shared = {}, fragments = []) => {
|
this.check = ([i, j], string, inputs, shared = {}, fragments = []) => {
|
||||||
|
|
||||||
/** @type {[string, Array.<string>]} */
|
/** @type {[string, Array.<string>]} */
|
||||||
const [separator, items] = (
|
const [separator, original_items] = (
|
||||||
Check.is_string(inputs) ? ((_, separator, items) => [
|
Check.is_string(inputs) ? ((_, separator, items) => [
|
||||||
separator, items.split("|")
|
separator, items.split("|")
|
||||||
])(...inputs.match(/^([^,]+),(.*)$/)) :
|
])(...inputs.match(/^([^,]+),(.*)$/)) :
|
||||||
Check.is_array(inputs) ? inputs :
|
Check.is_array(inputs) ? inputs :
|
||||||
[]),
|
[]),
|
||||||
|
/** @type {Array.<string>} */
|
||||||
|
items = format.get_list([i, j], [...original_items]),
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
l = items.length;
|
l = items.length;
|
||||||
|
|
||||||
return format.check_select(string, [[l, l], separator, items], shared, fragments);
|
return format.check_select([i, j], string, [[l, l], separator, items], shared, fragments);
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor();
|
constructor();
|
||||||
|
|||||||
@ -40,18 +40,20 @@ export const PlainFormat = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!(string|Array.<any|null>)} inputs
|
* @param {!(string|Array.<any|null>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
* @param {!Array.<string>} [fragments = []]
|
* @param {!Array.<string>} [fragments = []]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.get = (inputs, shared = {}, fragments = []) => format.execute(
|
this.get = ([i, j], inputs, shared = {}, fragments = []) => format.execute([i, j],
|
||||||
Check.is_string(inputs) ? inputs :
|
Check.is_string(inputs) ? inputs :
|
||||||
Check.is_string(inputs[0]) ? inputs[0] :
|
Check.is_string(inputs[0]) ? inputs[0] :
|
||||||
"", shared, fragments);
|
"", shared, fragments);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!(string|Array.<string>)} inputs
|
* @param {!(string|Array.<string>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -59,7 +61,7 @@ export const PlainFormat = (function(){
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.check = (string, inputs, shared = {}, fragments = []) => {
|
this.check = ([i, j], string, inputs, shared = {}, fragments = []) => {
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
const substring = format.set_fragments_level((
|
const substring = format.set_fragments_level((
|
||||||
@ -68,7 +70,7 @@ export const PlainFormat = (function(){
|
|||||||
""), fragments);
|
""), fragments);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
/\{[^\{\}]+\}/.test(format.set_fragments_level(substring, fragments)) ? format.get_check_length(string, [substring], shared, fragments, false) :
|
/\{[^\{\}]+\}/.test(format.set_fragments_level(substring, fragments)) ? format.get_check_length([i, j], string, [substring], shared, fragments, false) :
|
||||||
FormatModule.prepare_result(string, substring, shared));
|
FormatModule.prepare_result(string, substring, shared));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -40,18 +40,20 @@ export const RandomFormat = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!(string|Array.<any|null>)} inputs
|
* @param {!(string|Array.<any|null>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
* @param {!Array.<string>} [fragments = []]
|
* @param {!Array.<string>} [fragments = []]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.get = (inputs, shared = {}, fragments = []) => format.execute(Utils.get_random(
|
this.get = ([i, j], inputs, shared = {}, fragments = []) => format.execute([i, j], Utils.get_random(format.get_list([i, j], (
|
||||||
Check.is_string(inputs) ? inputs.split("|") :
|
Check.is_string(inputs) ? inputs.split("|") :
|
||||||
Check.is_array(inputs[0]) ? inputs[0] :
|
Check.is_array(inputs[0]) ? inputs[0] :
|
||||||
[]), shared, fragments);
|
[]))), shared, fragments);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!(string|Array.<string>)} inputs
|
* @param {!(string|Array.<string>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -59,21 +61,21 @@ export const RandomFormat = (function(){
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.check = (string, inputs, shared = {}, fragments = []) => {
|
this.check = ([i, j], string, inputs, shared = {}, fragments = []) => {
|
||||||
|
|
||||||
/** @type {boolean} */
|
/** @type {boolean} */
|
||||||
let has_empty = false;
|
let has_empty = false;
|
||||||
|
|
||||||
for(const option of (
|
for(const option of format.get_list([i, j], (
|
||||||
Check.is_string(inputs) ? inputs.split("|") :
|
Check.is_string(inputs) ? inputs.split("|") :
|
||||||
Check.is_array(inputs[0]) ? inputs[0] :
|
Check.is_array(inputs[0]) ? inputs[0] :
|
||||||
[])){
|
[]))){
|
||||||
if(!option){
|
if(!option){
|
||||||
has_empty = true;
|
has_empty = true;
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if(/\{[^\{\}]+\}/.test(format.set_fragments_level(option, fragments)))
|
if(/\{[^\{\}]+\}/.test(format.set_fragments_level(option, fragments)))
|
||||||
return format.get_check_length(string, [option], shared, fragments, false);
|
return format.get_check_length([i, j], string, [option], shared, fragments, false);
|
||||||
|
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
let length = FormatModule.prepare_result(string, option, shared);
|
let length = FormatModule.prepare_result(string, option, shared);
|
||||||
|
|||||||
@ -39,13 +39,14 @@ export const RangeFormat = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!(string|Array.<any|null>)} inputs
|
* @param {!(string|Array.<any|null>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
* @param {!Array.<string>} [fragments = []]
|
* @param {!Array.<string>} [fragments = []]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.get = (inputs, shared = {}, fragments = []) => {
|
this.get = ([i, j], inputs, shared = {}, fragments = []) => {
|
||||||
|
|
||||||
if(Check.is_number(inputs = (
|
if(Check.is_number(inputs = (
|
||||||
Check.is_string(inputs) ? Utils.get_random(inputs.split("|")).split("-").map(Number) :
|
Check.is_string(inputs) ? Utils.get_random(inputs.split("|")).split("-").map(Number) :
|
||||||
@ -63,6 +64,7 @@ export const RangeFormat = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!(string|Array.<string>)} inputs
|
* @param {!(string|Array.<string>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -70,7 +72,7 @@ export const RangeFormat = (function(){
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.check = (string, inputs, shared = {}, fragments = []) => FormatModule.check_range(string, inputs);
|
this.check = ([i, j], string, inputs, shared = {}, fragments = []) => FormatModule.check_range(string, inputs);
|
||||||
|
|
||||||
constructor();
|
constructor();
|
||||||
|
|
||||||
|
|||||||
@ -37,22 +37,23 @@ export const SelectFormat = (function(){
|
|||||||
const constructor = () => {
|
const constructor = () => {
|
||||||
format.modes.select = self.get;
|
format.modes.select = self.get;
|
||||||
format.checks.select = self.check;
|
format.checks.select = self.check;
|
||||||
format.modes.Select = (inputs, shared, fragments) => self.get(inputs, {
|
format.modes.Select = ([i, j], inputs, shared, fragments) => self.get([i, j], inputs, {
|
||||||
...shared, capitalized : true
|
...shared, capitalized : true
|
||||||
}, fragments);
|
}, fragments);
|
||||||
format.checks.Select = (string, inputs, shared, fragments) => self.check(string, inputs, {
|
format.checks.Select = ([i, j], string, inputs, shared, fragments) => self.check([i, j], string, inputs, {
|
||||||
...shared, capitalized : true
|
...shared, capitalized : true
|
||||||
}, fragments);
|
}, fragments);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!(string|Array.<any|null>)} inputs
|
* @param {!(string|Array.<any|null>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
* @param {!Array.<string>} [fragments = []]
|
* @param {!Array.<string>} [fragments = []]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.get = (inputs, shared = {}, fragments = []) => {
|
this.get = ([i, j], inputs, shared = {}, fragments = []) => {
|
||||||
|
|
||||||
/** @type {[[number, number], string, Array.<string>]} */
|
/** @type {[[number, number], string, Array.<string>]} */
|
||||||
const [range, separator, original_items] = (
|
const [range, separator, original_items] = (
|
||||||
@ -62,13 +63,13 @@ export const SelectFormat = (function(){
|
|||||||
Check.is_array(inputs) ? inputs :
|
Check.is_array(inputs) ? inputs :
|
||||||
[]),
|
[]),
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
i = Utils.get_random(...range);
|
k = Utils.get_random(...range);
|
||||||
|
|
||||||
if(!i)
|
if(!k)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
/** @type {Array.<string>} */
|
/** @type {Array.<string>} */
|
||||||
const items = [...original_items];
|
const items = format.get_list([i, j], [...original_items]);
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
let l = items.length,
|
let l = items.length,
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
@ -79,7 +80,7 @@ export const SelectFormat = (function(){
|
|||||||
else{
|
else{
|
||||||
|
|
||||||
Utils.randomize_array(items);
|
Utils.randomize_array(items);
|
||||||
items.splice(0, l - i);
|
items.splice(0, l - k);
|
||||||
l = items.length;
|
l = items.length;
|
||||||
|
|
||||||
results = (
|
results = (
|
||||||
@ -90,12 +91,13 @@ export const SelectFormat = (function(){
|
|||||||
separator) + items[l - 1]);
|
separator) + items[l - 1]);
|
||||||
|
|
||||||
};
|
};
|
||||||
results = format.execute(results, shared, fragments);
|
results = format.execute([i, j], results, shared, fragments);
|
||||||
|
|
||||||
return shared.capitalized ? results.replace(/^./, character => character.toUpperCase()) : results;
|
return shared.capitalized ? results.replace(/^./, character => character.toUpperCase()) : results;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!(string|Array.<string>)} inputs
|
* @param {!(string|Array.<string>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -103,12 +105,20 @@ export const SelectFormat = (function(){
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.check = (string, inputs, shared = {}, fragments = []) => format.check_select(string, (
|
this.check = ([i, j], string, inputs, shared = {}, fragments = []) => {
|
||||||
Check.is_string(inputs) ? ((_, range, separator, options) => [
|
|
||||||
range.split("-").map(Number), separator, options.split("|")
|
/** @type {[[number, number], string, Array.<string>]} */
|
||||||
])(...inputs.match(/^([^,]+),([^,]+),(.*)$/)) :
|
const [[minimum, maximum], separator, original_items] = (
|
||||||
Check.is_array(inputs) ? inputs :
|
Check.is_string(inputs) ? ((_, range, separator, options) => [
|
||||||
[]), shared, fragments);
|
range.split("-").map(Number), separator, options.split("|")
|
||||||
|
])(...inputs.match(/^([^,]+),([^,]+),(.*)$/)) :
|
||||||
|
Check.is_array(inputs) ? inputs :
|
||||||
|
[]),
|
||||||
|
/** @type {Array.<string>} */
|
||||||
|
items = format.get_list([i, j], [...original_items]);
|
||||||
|
|
||||||
|
return format.check_select([i, j], string, [[minimum, maximum], separator, items], shared, fragments);
|
||||||
|
};
|
||||||
|
|
||||||
constructor();
|
constructor();
|
||||||
|
|
||||||
|
|||||||
@ -39,13 +39,14 @@ export const SerieFormat = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!(string|Array.<any|null>)} inputs
|
* @param {!(string|Array.<any|null>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
* @param {!Array.<string>} [fragments = []]
|
* @param {!Array.<string>} [fragments = []]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.get = (inputs, shared = {}, fragments = []) => {
|
this.get = ([i, j], inputs, shared = {}, fragments = []) => {
|
||||||
|
|
||||||
Check.is_string(inputs) &&
|
Check.is_string(inputs) &&
|
||||||
(inputs = inputs.split("|").map(range => range.split("-").map(Number)));
|
(inputs = inputs.split("|").map(range => range.split("-").map(Number)));
|
||||||
@ -73,6 +74,7 @@ export const SerieFormat = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!(string|Array.<string>)} inputs
|
* @param {!(string|Array.<string>)} inputs
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -80,7 +82,7 @@ export const SerieFormat = (function(){
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.check = (string, inputs, shared = {}, fragments = []) => FormatModule.check_range(string, inputs);
|
this.check = ([i, j], string, inputs, shared = {}, fragments = []) => FormatModule.check_range(string, inputs);
|
||||||
|
|
||||||
constructor();
|
constructor();
|
||||||
|
|
||||||
|
|||||||
@ -85,6 +85,22 @@ export const FormatModule = (function(){
|
|||||||
const constructor = () => {};
|
const constructor = () => {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {![number, number]} coordenates
|
||||||
|
* @param {!string} key
|
||||||
|
* @returns {[string, ...(any|null)]|null}
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
this.get_variable = ([i, j], key) => {
|
||||||
|
// key == "l_40_2015" && console.log([i, j, key, ot.variables]);
|
||||||
|
return (
|
||||||
|
(ot.database[i].queries[j].own_variables && ot.database[i].queries[j].own_variables[key]) ||
|
||||||
|
(ot.group_variables[ot.database[i].group] && ot.group_variables[ot.database[i].group][key]) ||
|
||||||
|
ot.variables[key]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!(string|Array.<string>)} options
|
* @param {!(string|Array.<string>)} options
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -93,15 +109,16 @@ export const FormatModule = (function(){
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.get_check_length = (string, options, shared = {}, fragments = [], check_full = true) => {
|
this.get_check_length = ([i, j], string, options, shared = {}, fragments = [], check_full = true) => {
|
||||||
|
|
||||||
/** @type {[boolean, number]} */
|
/** @type {[boolean, number]} */
|
||||||
const [has, length] = self.check(string, options, shared, fragments, check_full);
|
const [has, length] = self.check([i, j], string, options, shared, fragments, check_full);
|
||||||
|
|
||||||
return has ? length : -1;
|
return has ? length : -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!(string|Array.<string>)} options
|
* @param {!(string|Array.<string>)} options
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -110,7 +127,7 @@ export const FormatModule = (function(){
|
|||||||
* @returns {[boolean, number]}
|
* @returns {[boolean, number]}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.check = (string, options, shared = {}, fragments = [], check_full = true) => {
|
this.check = ([i, j], string, options, shared = {}, fragments = [], check_full = true) => {
|
||||||
|
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
let length = 0;
|
let length = 0;
|
||||||
@ -132,10 +149,10 @@ export const FormatModule = (function(){
|
|||||||
});
|
});
|
||||||
length = 0;
|
length = 0;
|
||||||
|
|
||||||
return parts.every((part, i) => {
|
return parts.every((part, k) => {
|
||||||
|
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
let j = -1;
|
let m = -1;
|
||||||
/** @type {RegExpMatchArray} */
|
/** @type {RegExpMatchArray} */
|
||||||
const matches = part.match(/^\{([^\{\}]+)\}$/);
|
const matches = part.match(/^\{([^\{\}]+)\}$/);
|
||||||
|
|
||||||
@ -148,15 +165,15 @@ export const FormatModule = (function(){
|
|||||||
if(key in ot.variables){
|
if(key in ot.variables){
|
||||||
|
|
||||||
/** @type {[string, ...(any|null)]} */
|
/** @type {[string, ...(any|null)]} */
|
||||||
const [method, ...data] = ot.variables[key];
|
const [method, ...data] = self.get_variable([i, j], key);
|
||||||
|
|
||||||
method in self.checks &&
|
method in self.checks &&
|
||||||
// self.checks[method](clone, data, shared, fragments) != -1 &&
|
// self.checks[method]([i, j], clone, data, shared, fragments) != -1 &&
|
||||||
(j = self.checks[method](clone, data, shared, fragments));
|
(m = self.checks[method]([i, j], clone, data, shared, fragments));
|
||||||
|
|
||||||
}else if(parts[i + 1]){
|
}else if(parts[k + 1]){
|
||||||
// TEMPORARY SOLUTION. NEEDS BUILD REAL SOLUTION.
|
// TEMPORARY SOLUTION. NEEDS BUILD REAL SOLUTION.
|
||||||
j = clone.indexOf(parts[i + 1]);
|
m = clone.indexOf(parts[k + 1]);
|
||||||
};
|
};
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
@ -169,16 +186,16 @@ export const FormatModule = (function(){
|
|||||||
const [method, data] = matches.slice(1, 3);
|
const [method, data] = matches.slice(1, 3);
|
||||||
|
|
||||||
method in self.checks &&
|
method in self.checks &&
|
||||||
(j = self.checks[method](clone, data, shared, fragments));
|
(m = self.checks[method]([i, j], clone, data, shared, fragments));
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
j == -1 && (j = FormatModule.prepare_result(clone, part, shared));
|
m == -1 && (m = FormatModule.prepare_result(clone, part, shared));
|
||||||
|
|
||||||
if(j != -1){
|
if(m != -1){
|
||||||
clone = clone.slice(j);
|
clone = clone.slice(m);
|
||||||
length += j;
|
length += m;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
return false;
|
return false;
|
||||||
@ -214,26 +231,31 @@ export const FormatModule = (function(){
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
* @param {!Array.<string>} [fragments = []]
|
* @param {!Array.<string>} [fragments = []]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.execute = (string, shared = {}, fragments = []) => (
|
this.execute = ([i, j], string, shared = {}, fragments = []) => (
|
||||||
FormatModule.recursive(self.build_fragments(string, fragments), substring => {
|
FormatModule.recursive(self.build_fragments(string, fragments), substring => {
|
||||||
try{
|
try{
|
||||||
return substring.replace(/\{([^\{\}]+)\}/g, (original, key) => {
|
return substring.replace(/\{([^\{\}]+)\}/g, (original, key) => {
|
||||||
if(/^[a-z0-9_]+$/i.test(key)){
|
if(/^[a-z0-9_]+$/i.test(key)){
|
||||||
if(key in shared)
|
if(key in shared)
|
||||||
return shared[key];
|
return shared[key];
|
||||||
else if(key in ot.variables){
|
|
||||||
|
/** @type {[string, ...(any|null)]|null} */
|
||||||
|
const variable = self.get_variable([i, j], key);
|
||||||
|
|
||||||
|
if(variable){
|
||||||
|
|
||||||
/** @type {[string, ...(any|null)]} */
|
/** @type {[string, ...(any|null)]} */
|
||||||
const [method, ...data] = ot.variables[key];
|
const [method, ...data] = variable;
|
||||||
|
|
||||||
if(method in self.modes)
|
if(method in self.modes)
|
||||||
return self.modes[method](data, shared, fragments);
|
return self.modes[method]([i, j], data, shared, fragments);
|
||||||
};
|
};
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
@ -246,7 +268,7 @@ export const FormatModule = (function(){
|
|||||||
const [method, data] = matches.slice(1, 3);
|
const [method, data] = matches.slice(1, 3);
|
||||||
|
|
||||||
if(method in self.modes)
|
if(method in self.modes)
|
||||||
return self.modes[method](data, shared, fragments);
|
return self.modes[method]([i, j], data, shared, fragments);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
return original
|
return original
|
||||||
@ -259,6 +281,7 @@ export const FormatModule = (function(){
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
* @param {!string} string
|
* @param {!string} string
|
||||||
* @param {[[number, number], string, Array.<string>]} parameters
|
* @param {[[number, number], string, Array.<string>]} parameters
|
||||||
* @param {!Object.<string, any|null>} [shared = {}]
|
* @param {!Object.<string, any|null>} [shared = {}]
|
||||||
@ -266,7 +289,7 @@ export const FormatModule = (function(){
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
this.check_select = (string, [[minimum, maximum], separator, items], shared = {}, fragments = []) => {
|
this.check_select = ([i, j], string, [[minimum, maximum], separator, items], shared = {}, fragments = []) => {
|
||||||
|
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
let length = 0,
|
let length = 0,
|
||||||
@ -291,16 +314,16 @@ export const FormatModule = (function(){
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for(let i = 0; i < l; i ++){
|
for(let m = 0; m < l; m ++){
|
||||||
|
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
const item_length = (
|
const item_length = (
|
||||||
/\{[^\{\}]+\}/.test(self.set_fragments_level(items[i], shared, fragments)) ? self.get_check_length(string, [items[i]], shared, fragments, false) :
|
/\{[^\{\}]+\}/.test(self.set_fragments_level(items[m], shared, fragments)) ? self.get_check_length([i, j], string, [items[m]], shared, fragments, false) :
|
||||||
FormatModule.prepare_result(string, items[i], shared));
|
FormatModule.prepare_result(string, items[m], shared));
|
||||||
|
|
||||||
if(item_length != -1){
|
if(item_length != -1){
|
||||||
string = string.substring(0, item_length);
|
string = string.substring(0, item_length);
|
||||||
items.splice(i, 1);
|
items.splice(m, 1);
|
||||||
length += item_length;
|
length += item_length;
|
||||||
ok = true;
|
ok = true;
|
||||||
break;
|
break;
|
||||||
@ -322,6 +345,30 @@ export const FormatModule = (function(){
|
|||||||
return k < minimum ? -1 : length;
|
return k < minimum ? -1 : length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {[number, number]} coordenates
|
||||||
|
* @param {!Array.<string>} items
|
||||||
|
* @returns {Array.<string>}
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
this.get_list = ([i, j], items) => items.reduce((items, item) => {
|
||||||
|
|
||||||
|
/** @type {RegExpMatchArray} */
|
||||||
|
const matches = item.match(/^list\:([a-z0-9_]+)$/i);
|
||||||
|
|
||||||
|
if(matches){
|
||||||
|
|
||||||
|
/** @type {string} */
|
||||||
|
const key = matches[1],
|
||||||
|
/** @type {[string, ...(any|null)]|null} */
|
||||||
|
variable = self.get_variable([i, j], key);
|
||||||
|
|
||||||
|
if(variable[0] == "list")
|
||||||
|
return items.concat(variable[1]);
|
||||||
|
};
|
||||||
|
return items.concat([item]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
constructor();
|
constructor();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -148,6 +148,16 @@ export const Utils = (function(){
|
|||||||
upper ? "-" + upper.toLowerCase() :
|
upper ? "-" + upper.toLowerCase() :
|
||||||
"-"));
|
"-"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!string} string
|
||||||
|
* @returns {string}
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
Utils.to_snake_case = string => ("" + string).replace(/([A-Z]+)|[^a-z0-9]+/g, (_, upper) => (
|
||||||
|
upper ? "_" + upper.toLowerCase() :
|
||||||
|
"_"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!HTMLElement} item
|
* @param {!HTMLElement} item
|
||||||
* @param {...Object.<string, any|null>} attributes
|
* @param {...Object.<string, any|null>} attributes
|
||||||
|
|||||||
@ -55,6 +55,7 @@ export const TestsView = (function(){
|
|||||||
]];
|
]];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {![number, number]} coordenates
|
||||||
* @param {!Array.<[string, boolean, boolean]>} originals
|
* @param {!Array.<[string, boolean, boolean]>} originals
|
||||||
* @param {!Array.<[string, boolean]>} raw_answers
|
* @param {!Array.<[string, boolean]>} raw_answers
|
||||||
* @param {boolean} right
|
* @param {boolean} right
|
||||||
@ -62,7 +63,7 @@ export const TestsView = (function(){
|
|||||||
* @access public
|
* @access public
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
const replace_answer = (originals, raw_answers, right, number_of_answers) => {
|
const replace_answer = ([i, j], originals, raw_answers, right, number_of_answers) => {
|
||||||
|
|
||||||
/** @type {Array.<[string, boolean, boolean]>} */
|
/** @type {Array.<[string, boolean, boolean]>} */
|
||||||
const set = originals.filter(([_, ok]) => right ? ok : !ok);
|
const set = originals.filter(([_, ok]) => right ? ok : !ok);
|
||||||
@ -78,7 +79,7 @@ export const TestsView = (function(){
|
|||||||
if(!probability || Math.random() < probability){
|
if(!probability || Math.random() < probability){
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
const string_answer = dynamic ? ot.format.execute(answer) : answer;
|
const string_answer = dynamic ? ot.format.execute([i, j], answer) : answer;
|
||||||
|
|
||||||
if(raw_answers.length < number_of_answers)
|
if(raw_answers.length < number_of_answers)
|
||||||
raw_answers.some(([originals, ok]) => ok && originals == string_answer) ||
|
raw_answers.some(([originals, ok]) => ok && originals == string_answer) ||
|
||||||
@ -197,7 +198,7 @@ export const TestsView = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
if(dynamic)
|
if(dynamic)
|
||||||
answer = ot.format.execute(answer);
|
answer = ot.format.execute([i, j], answer);
|
||||||
else
|
else
|
||||||
originals.splice(k, 1);
|
originals.splice(k, 1);
|
||||||
|
|
||||||
@ -212,6 +213,7 @@ export const TestsView = (function(){
|
|||||||
// ),
|
// ),
|
||||||
|
|
||||||
// ot.format.check(
|
// ot.format.check(
|
||||||
|
// [i, j],
|
||||||
// answer,
|
// answer,
|
||||||
// originals.map(([[base, __], right, _]) => (
|
// originals.map(([[base, __], right, _]) => (
|
||||||
// right ? base : null
|
// right ? base : null
|
||||||
@ -225,6 +227,7 @@ export const TestsView = (function(){
|
|||||||
// answer &&
|
// answer &&
|
||||||
// !raw_answers.some(([base, _]) => answer == base) &&
|
// !raw_answers.some(([base, _]) => answer == base) &&
|
||||||
// !ot.format.check(
|
// !ot.format.check(
|
||||||
|
// [i, j],
|
||||||
// answer,
|
// answer,
|
||||||
// originals.map(([[base, __], right, _]) => (
|
// originals.map(([[base, __], right, _]) => (
|
||||||
// right ? base : null
|
// right ? base : null
|
||||||
@ -238,6 +241,7 @@ export const TestsView = (function(){
|
|||||||
answer &&
|
answer &&
|
||||||
!(raw_answers.length && raw_answers.some(([base, _]) => answer == base)) &&
|
!(raw_answers.length && raw_answers.some(([base, _]) => answer == base)) &&
|
||||||
!ot.format.check(
|
!ot.format.check(
|
||||||
|
[i, j],
|
||||||
answer,
|
answer,
|
||||||
originals.map(([[base, __], right, _]) => (
|
originals.map(([[base, __], right, _]) => (
|
||||||
right ? base : null
|
right ? base : null
|
||||||
@ -258,9 +262,9 @@ export const TestsView = (function(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
if(!raw_answers.some(([_, ok]) => ok) && (!data.allow_all_answers_false || !multiple_answers))
|
if(!raw_answers.some(([_, ok]) => ok) && (!data.allow_all_answers_false || !multiple_answers))
|
||||||
replace_answer(originals, raw_answers, true, number_of_answers);
|
replace_answer([i, j], originals, raw_answers, true, number_of_answers);
|
||||||
else if(!raw_answers.some(([_, ok]) => !ok) && !data.allow_all_answers_true)
|
else if(!raw_answers.some(([_, ok]) => !ok) && !data.allow_all_answers_true)
|
||||||
replace_answer(originals, raw_answers, false, number_of_answers);
|
replace_answer([i, j], originals, raw_answers, false, number_of_answers);
|
||||||
|
|
||||||
raw_answers.length < number_of_answers && console.warn([q, raw_answers, memory]);
|
raw_answers.length < number_of_answers && console.warn([q, raw_answers, memory]);
|
||||||
|
|
||||||
@ -291,7 +295,7 @@ export const TestsView = (function(){
|
|||||||
ot.comp.i18n("unanswered")
|
ot.comp.i18n("unanswered")
|
||||||
]]
|
]]
|
||||||
]],
|
]],
|
||||||
["p", null, ot.format.execute(Check.is_array(ot.database[i].queries[j].question) ? Utils.get_random(ot.database[i].queries[j].question) : ot.database[i].queries[j].question)],
|
["p", null, ot.format.execute([i, j], Check.is_array(ot.database[i].queries[j].question) ? Utils.get_random(ot.database[i].queries[j].question) : ot.database[i].queries[j].question)],
|
||||||
["ul", {class : "answers"}, answers.map((answer, i) => ["li", {data_i : i}, [
|
["ul", {class : "answers"}, answers.map((answer, i) => ["li", {data_i : i}, [
|
||||||
ot.comp[multiple_answers ? "checkbox" : "radio"]("q" + q + "[]", false, (item, event) => {
|
ot.comp[multiple_answers ? "checkbox" : "radio"]("q" + q + "[]", false, (item, event) => {
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
"/json/gemini/constitucion-espanola/gemini.ce.166.json",
|
"/json/gemini/constitucion-espanola/gemini.ce.166.json",
|
||||||
|
|
||||||
|
"/json/kyman/comun/kyman.-1.leyes.json",
|
||||||
"/json/kyman/comun/kyman.-0.diccionario.json",
|
"/json/kyman/comun/kyman.-0.diccionario.json",
|
||||||
|
|
||||||
"/json/kyman/comun/kyman.00.tipos-leyes.json",
|
"/json/kyman/comun/kyman.00.tipos-leyes.json",
|
||||||
"/json/paco/constitucion/paco.ce.00.constitucion.json",
|
"/json/paco/constitucion/paco.ce.00.constitucion.json",
|
||||||
"/json/paco/constitucion/paco.ce.01.0.constitucion.preliminar.json",
|
"/json/paco/constitucion/paco.ce.01.0.constitucion.preliminar.json",
|
||||||
@ -26,6 +28,10 @@
|
|||||||
"/json/kyman/especifico/kyman.02.hardware.00.ics.json",
|
"/json/kyman/especifico/kyman.02.hardware.00.ics.json",
|
||||||
"/json/kyman/especifico/kyman.03.desarrollo.02.codificaciones-texto.json",
|
"/json/kyman/especifico/kyman.03.desarrollo.02.codificaciones-texto.json",
|
||||||
"/json/kyman/especifico/kyman.aa.red-sara.json",
|
"/json/kyman/especifico/kyman.aa.red-sara.json",
|
||||||
|
"/json/kyman/especifico/kyman.ab.eni.json",
|
||||||
|
"/json/kyman/especifico/kyman.ac.eni.preguntas-frecuentes.json",
|
||||||
|
|
||||||
|
"/json/kyman/especifico/software/kyman.00.ping.json",
|
||||||
|
|
||||||
"/data/json/baquedano/c-ejer-1-promo-sass-2025.json",
|
"/data/json/baquedano/c-ejer-1-promo-sass-2025.json",
|
||||||
"/data/json/baquedano/c-ejer-1-libre-sas-2025.json",
|
"/data/json/baquedano/c-ejer-1-libre-sas-2025.json",
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
"BOP" : ["rand", ["BOP", "Boletín Oficial de la Provincia"]],
|
"BOP" : ["rand", ["BOP", "Boletín Oficial de la Provincia"]],
|
||||||
"DOGA" : ["rand", ["DOGA", "Diario Oficial de Galicia"]],
|
"DOGA" : ["rand", ["DOGA", "Diario Oficial de Galicia"]],
|
||||||
"BOD" : ["rand", ["BOD", "Boletín Oficial de Defensa"]],
|
"BOD" : ["rand", ["BOD", "Boletín Oficial de Defensa"]],
|
||||||
|
"TC" : ["rand", ["Tribunal Constitucional", "TC"]],
|
||||||
|
"AAPP" : ["rand", ["Administraciones Públicas", "AAPP"]],
|
||||||
|
|
||||||
"meses" : ["rand", ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]],
|
"meses" : ["rand", ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]],
|
||||||
|
|
||||||
@ -33,7 +35,8 @@
|
|||||||
"La Norma{rand:|s|ativa}{rand:| {rand:con|de} Rango {rand:de Ley|Reglamentario}}",
|
"La Norma{rand:|s|ativa}{rand:| {rand:con|de} Rango {rand:de Ley|Reglamentario}}",
|
||||||
"La {rand:Resolu{rand:ción|tiva}|Orden{rand:|amiento}}{rand:| Judicial| Administrativa| Técnica| Ministerial}"
|
"La {rand:Resolu{rand:ción|tiva}|Orden{rand:|amiento}}{rand:| Judicial| Administrativa| Técnica| Ministerial}"
|
||||||
]],
|
]],
|
||||||
"ley" : ["plain", "{tipo_ley_random_el} {range:1-99}/{rand:{range:1978-2025}|{range:1918-2025}}{rand:|, de {range:1-31} de {meses}}"],
|
"ley" : ["plain", "{tipo_ley_random_el} {range:1-99}/{rand:{range:1918-2025}|{range:1918-2025}}{rand:|, de {range:1-31} de {meses}}"],
|
||||||
|
"ley_base" : ["plain", "{range:1-600}/{rand:{range:1918-2025}|{range:1918-2025}}{rand:|, de {range:1-31} de {meses}}"],
|
||||||
"cortes_generales" : ["rand", ["Cortes Generales", "Poder Legislativo"]],
|
"cortes_generales" : ["rand", ["Cortes Generales", "Poder Legislativo"]],
|
||||||
"gobierno" : ["rand", ["Gobierno", "Poder Ejecutivo"]],
|
"gobierno" : ["rand", ["Gobierno", "Poder Ejecutivo"]],
|
||||||
"poder_judicial" : ["rand", ["Poder Judicial", "{mix:y,Jueces|Tribunales}"]],
|
"poder_judicial" : ["rand", ["Poder Judicial", "{mix:y,Jueces|Tribunales}"]],
|
||||||
@ -113,8 +116,6 @@
|
|||||||
"27 de Septiembre de 2011",
|
"27 de Septiembre de 2011",
|
||||||
"15 de Febrero de 2024"
|
"15 de Febrero de 2024"
|
||||||
]],
|
]],
|
||||||
"ce78_alternativas" : ["rand", ["Ley de Leyes", "Carta Magna", "Norma Suprema"]],
|
|
||||||
"ce78" : ["plain", "{rand:{ce78_alternativas}|Constitución}{rand:| Española}{rand:| de 1978}"],
|
|
||||||
"ce78_establece" : ["mix", "y", [
|
"ce78_establece" : ["mix", "y", [
|
||||||
"la estructura del Estado",
|
"la estructura del Estado",
|
||||||
"la organización de los poderes públicos",
|
"la organización de los poderes públicos",
|
||||||
@ -254,68 +255,9 @@
|
|||||||
"TREBEP" : ["rand", ["TREBEP", "Texto Refundido de la Ley del Estatuto Básico del Empleado Público", "{RDL} 5/2015{rand:|, de 30 de Octubre}"]],
|
"TREBEP" : ["rand", ["TREBEP", "Texto Refundido de la Ley del Estatuto Básico del Empleado Público", "{RDL} 5/2015{rand:|, de 30 de Octubre}"]],
|
||||||
"EBEP" : ["rand", ["EBEP", "Estatuto Básico del Empleado Público", "Ley 7/2007{rand:|, de 12 de Abril}"]],
|
"EBEP" : ["rand", ["EBEP", "Estatuto Básico del Empleado Público", "Ley 7/2007{rand:|, de 12 de Abril}"]],
|
||||||
|
|
||||||
"trebep_ley" : ["plain", "{RDL} 5/2015{rand:|, de 30 de Octubre}"],
|
"RD" : ["rand", ["RD", "Real Decreto", "Decreto"]],
|
||||||
"trebep_nombre" : ["rand", [
|
|
||||||
"TREBEP",
|
|
||||||
"Texto Refundido de la Ley del Estatuto Básico del Empleado Público"
|
|
||||||
]],
|
|
||||||
"trebep" : ["rand", [
|
|
||||||
"{trebep_nombre}",
|
|
||||||
"{trebep_ley}{rand:|, por el que se aprueba el {trebep_nombre}}"
|
|
||||||
]],
|
|
||||||
"ebep_ley" : ["plain", "Ley 7/2007{rand:|, de 12 de Abril}"],
|
|
||||||
"ebep_nombre" : ["rand", [
|
|
||||||
"EBEP",
|
|
||||||
"Estatuto Básico del Empleado Público"
|
|
||||||
]],
|
|
||||||
"ebep" : ["rand", [
|
|
||||||
"{ebep_nombre}",
|
|
||||||
"{ebep_ley}{rand:|, por el que se aprueba el {ebep_nombre}}"
|
|
||||||
]],
|
|
||||||
"RD" : ["rand", ["{RD}", "Real Decreto", "Decreto"]],
|
|
||||||
"RD_RDL" : ["rand", ["{RDL}", "{RD}"]],
|
"RD_RDL" : ["rand", ["{RDL}", "{RD}"]],
|
||||||
"LO" : ["rand", ["Ley Orgánica", "LO"]],
|
"LO" : ["rand", ["Ley Orgánica", "LO"]],
|
||||||
"rd_364_1995_ley" : ["plain", "{rand:RD|RDL} 364/1995{rand:|, de 10 de Marzo}"],
|
|
||||||
"rd_364_1995_nombre" : ["plain", "Reglamento General de Ingreso del Personal al servicio de la Administración general del Estado y de Provisión de Puestos de Trabajo y Promoción Profesional de los Funcionarios Civiles de la Administración general del Estado"],
|
|
||||||
"rd_365_1995_ley" : ["plain", "{rand:RD|RDL} 365/1995{rand:|, de 10 de Marzo}"],
|
|
||||||
"rd_364_1995" : ["rand", [
|
|
||||||
"{rd_364_1995_nombre}",
|
|
||||||
"{rd_364_1995_ley}{rand:|, por el que se aprueba el {rd_364_1995_nombre}}"
|
|
||||||
]],
|
|
||||||
"rd_365_1995_nombre" : ["plain", "Reglamento de Situaciones Administrativas de los Funcionarios Civiles de la Administración General del Estado"],
|
|
||||||
"rd_365_1995" : ["rand", [
|
|
||||||
"{rd_365_1995_nombre}",
|
|
||||||
"{rd_365_1995_ley}{rand:|, por el que se aprueba el {rd_365_1995_nombre}}"
|
|
||||||
]],
|
|
||||||
"l_30_30_1984_ley" : ["plain", "Ley 30/1984{rand:|, de 2 de Agosto}"],
|
|
||||||
"l_30_30_1984_nombre" : ["plain", "Ley de Medidas para la Reforma de la Función Pública"],
|
|
||||||
"l_30_30_1984" : ["rand", [
|
|
||||||
"{l_30_30_1984_nombre}",
|
|
||||||
"{l_30_30_1984_ley}{rand:|, por el que se aprueba el {l_30_30_1984_nombre}}"
|
|
||||||
]],
|
|
||||||
"d_315_1964_ley" : ["plain", "Decreto 315/1964{rand:|, de 7 de Febrero}"],
|
|
||||||
"d_315_1964_nombre" : ["plain", "Ley articulada de Funcionarios Civiles del Estado"],
|
|
||||||
"d_315_1964" : ["rand", [
|
|
||||||
"{d_315_1964_nombre}",
|
|
||||||
"{d_315_1964_ley}{rand:|, por el que se aprueba el {d_315_1964_nombre}}"
|
|
||||||
]],
|
|
||||||
"TC" : ["rand", ["Tribunal Constitucional", "TC"]],
|
|
||||||
"rdl_2_2015_ley" : ["plain", "{RDL} 2/2015{rand:|, de 23 de Octubre}"],
|
|
||||||
"rdl_2_2015_nombre" : ["plain", "Texto Refundido de la Ley del Estatuto de los Trabajadores"],
|
|
||||||
"rdl_2_2015" : ["rand", [
|
|
||||||
"{rdl_2_2015_nombre}",
|
|
||||||
"{rdl_2_2015_ley}{rand:|, por el que se aprueba el {rdl_2_2015_nombre}}",
|
|
||||||
"Ley del Estatuto de los Trabajadores"
|
|
||||||
]],
|
|
||||||
"lo_2_1986_ley" : ["plain", "{LO} 2/1986{rand:|, de 13 de marzo}"],
|
|
||||||
"lo_2_1986_nombre" : ["plain", "Ley de Fuerzas y Cuerpos de Seguridad"],
|
|
||||||
"lo_2_1986" : ["plain", "{lo_2_1986_ley}{rand:|, {lo_2_1986_nombre}}"],
|
|
||||||
"l_53_1984_ley" : ["plain", "Ley 53/1984{rand:|, de 26 de Diciembre}"],
|
|
||||||
"l_53_1984_nombre" : ["plain", "Ley de Incompatibilidades del Personal al servicio de las Administraciones Públicas"],
|
|
||||||
"l_53_1984" : ["plain", "{l_53_1984_ley}{rand:|, {l_53_1984_nombre}}"],
|
|
||||||
"l_30_1984_ley" : ["plain", "Ley 30/1984{rand:|, de 2 de Agosto}"],
|
|
||||||
"l_30_1984_nombre" : ["plain", "Ley de Medidas para la Reforma de la Función Pública"],
|
|
||||||
"l_30_1984" : ["plain", "{l_30_1984_ley}{rand:|, {l_30_1984_nombre}}"],
|
|
||||||
"trebep_anos" : ["rand", ["2007", "2015", "1995", "1984", "1964", "1918"]],
|
"trebep_anos" : ["rand", ["2007", "2015", "1995", "1984", "1964", "1918"]],
|
||||||
"trebep_meses" : ["rand", ["Febrero", "Marzo", "Agosto", "Octubre", "Noviembre", "Diciembre", "Julio"]],
|
"trebep_meses" : ["rand", ["Febrero", "Marzo", "Agosto", "Octubre", "Noviembre", "Diciembre", "Julio"]],
|
||||||
"trebep_dias" : ["rand", ["1", "2", "10", "7", "23", "30", "31", "24"]],
|
"trebep_dias" : ["rand", ["1", "2", "10", "7", "23", "30", "31", "24"]],
|
||||||
@ -340,7 +282,10 @@
|
|||||||
"trebep_tv_ciii" : ["rand", ["Tercero", "3º", "Provisión de {mix:y,puestos de trabajo|movilidad}"]],
|
"trebep_tv_ciii" : ["rand", ["Tercero", "3º", "Provisión de {mix:y,puestos de trabajo|movilidad}"]],
|
||||||
"trebep_tvi" : ["rand", ["VI", "Sexto", "6º", "Situaciones administrativas"]],
|
"trebep_tvi" : ["rand", ["VI", "Sexto", "6º", "Situaciones administrativas"]],
|
||||||
"trebep_tvii" : ["rand", ["VII", "Séptimo", "7º", "Régimen disciplinario"]],
|
"trebep_tvii" : ["rand", ["VII", "Séptimo", "7º", "Régimen disciplinario"]],
|
||||||
"trebep_tviii" : ["rand", ["VIII", "Octavo", "8º", "Cooperación entre las Administraciones Públicas"]]
|
"trebep_tviii" : ["rand", ["VIII", "Octavo", "8º", "Cooperación entre las Administraciones Públicas"]],
|
||||||
|
|
||||||
|
"eni_nombre" : ["rand", ["ENI", "Esquema Nacional de Interoperabilidad"]],
|
||||||
|
"ens_nombre" : ["rand", ["ENS", "Esquema Nacional de Seguridad"]]
|
||||||
|
|
||||||
},
|
},
|
||||||
"queries" : []
|
"queries" : []
|
||||||
|
|||||||
131
Public/json/kyman/comun/kyman.-1.leyes.json
Normal file
131
Public/json/kyman/comun/kyman.-1.leyes.json
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
[{
|
||||||
|
"origin" : "KyMAN",
|
||||||
|
"sources" : [],
|
||||||
|
"title" : "Común - Leyes",
|
||||||
|
"group" : "kyman_comun_leyes",
|
||||||
|
"variables" : {
|
||||||
|
|
||||||
|
"l_30_30_1984_ley" : ["plain", "Ley 30/1984{rand:|, de 2 de Agosto}"],
|
||||||
|
"l_30_30_1984_nombre" : ["plain", "Ley de Medidas para la Reforma de la Función Pública"],
|
||||||
|
"l_30_30_1984" : ["rand", [
|
||||||
|
"{l_30_30_1984_nombre}",
|
||||||
|
"{l_30_30_1984_ley}{rand:|, por el que se aprueba el {l_30_30_1984_nombre}}"
|
||||||
|
]],
|
||||||
|
|
||||||
|
"ce78_alternativas" : ["rand", ["Ley de Leyes", "Carta Magna", "Norma Suprema"]],
|
||||||
|
"ce78" : ["plain", "{rand:{ce78_alternativas}|Constitución}{rand:| Española}{rand:| de 1978}"],
|
||||||
|
"trebep_ley" : ["plain", "{RDL} 5/2015{rand:|, de 30 de Octubre}"],
|
||||||
|
"trebep_nombre" : ["rand", [
|
||||||
|
"TREBEP",
|
||||||
|
"Texto Refundido de la Ley del Estatuto Básico del Empleado Público"
|
||||||
|
]],
|
||||||
|
"trebep" : ["rand", [
|
||||||
|
"{trebep_nombre}",
|
||||||
|
"{trebep_ley}{rand:|, por el que se aprueba el {trebep_nombre}}"
|
||||||
|
]],
|
||||||
|
"ebep_ley" : ["plain", "Ley 7/2007{rand:|, de 12 de Abril}"],
|
||||||
|
"ebep_nombre" : ["rand", [
|
||||||
|
"EBEP",
|
||||||
|
"Estatuto Básico del Empleado Público"
|
||||||
|
]],
|
||||||
|
"ebep" : ["rand", [
|
||||||
|
"{ebep_nombre}",
|
||||||
|
"{ebep_ley}{rand:|, por el que se aprueba el {ebep_nombre}}"
|
||||||
|
]],
|
||||||
|
"rgpd_ley" : ["plain", "Reglamento (UE) 2016/679{rand:|, de 27 de Abril}"],
|
||||||
|
"rgpd_nombre" : ["rand", ["Reglamento General de Protección de Datos", "RGPD"]],
|
||||||
|
"rgpd" : ["rand", [
|
||||||
|
"{rgpd_nombre}",
|
||||||
|
"{rgpd_ley}{rand:|, relativo a la protección de las personas físicas en lo que respecta al tratamiento de datos personales y a la libre circulación de estos datos{rand:| y por el que se deroga la {d_95_46_ce}}}"
|
||||||
|
]],
|
||||||
|
"lopd_ley" : ["plain", "Ley Orgánica 3/2018{rand:|, de 5 de Diciembre}"],
|
||||||
|
"lopd_nombre" : ["rand", [
|
||||||
|
"LOPD{rand:|GDD}",
|
||||||
|
"Ley Orgánica de Protección de Datos{rand:| Personales}{rand:| y garantía de los derechos digitales}",
|
||||||
|
"Ley Orgánica de Protección de Datos Personales y garantía de los derechos digitales"
|
||||||
|
]],
|
||||||
|
"lopd" : ["rand", [
|
||||||
|
"{lopd_nombre}",
|
||||||
|
"{lopd_ley}{rand:|, de Protección de Datos Personales y garantía de los derechos digitales}"
|
||||||
|
]],
|
||||||
|
|
||||||
|
"d_95_46_ce_ley" : ["plain", "Directiva 95/46/CE{rand:|, {mix:y,del Parlamento Europeo|del Consejo}}{rand:|, de 24 de Octubre de 1995}"],
|
||||||
|
"d_95_46_ce_nombre" : ["rand", ["Directiva de Protección de Datos"]],
|
||||||
|
"d_95_46_ce" : ["rand", [
|
||||||
|
"{d_95_46_ce_nombre}",
|
||||||
|
"{d_95_46_ce_ley}{rand:|, relativa a la protección de las personas físicas en lo respectivo al tratamiento de datos personales y a la libre circulación de estos datos}"
|
||||||
|
]],
|
||||||
|
"d_315_1964_ley" : ["plain", "Decreto 315/1964{rand:|, de 7 de Febrero}"],
|
||||||
|
"d_315_1964_nombre" : ["plain", "Ley articulada de Funcionarios Civiles del Estado"],
|
||||||
|
"d_315_1964" : ["rand", [
|
||||||
|
"{d_315_1964_nombre}",
|
||||||
|
"{d_315_1964_ley}{rand:|, por el que se aprueba el {d_315_1964_nombre}}"
|
||||||
|
]],
|
||||||
|
|
||||||
|
"rd_364_1995_ley" : ["plain", "{rand:RD|RDL} 364/1995{rand:|, de 10 de Marzo}"],
|
||||||
|
"rd_364_1995_nombre" : ["plain", "Reglamento General de Ingreso del Personal al servicio de la Administración general del Estado y de Provisión de Puestos de Trabajo y Promoción Profesional de los Funcionarios Civiles de la Administración general del Estado"],
|
||||||
|
"rd_364_1995" : ["rand", [
|
||||||
|
"{rd_364_1995_nombre}",
|
||||||
|
"{rd_364_1995_ley}{rand:|, por el que se aprueba el {rd_364_1995_nombre}}"
|
||||||
|
]],
|
||||||
|
"rd_365_1995_ley" : ["plain", "{rand:RD|RDL} 365/1995{rand:|, de 10 de Marzo}"],
|
||||||
|
"rd_365_1995_nombre" : ["plain", "Reglamento de Situaciones Administrativas de los Funcionarios Civiles de la Administración General del Estado"],
|
||||||
|
"rd_365_1995" : ["rand", [
|
||||||
|
"{rd_365_1995_nombre}",
|
||||||
|
"{rd_365_1995_ley}{rand:|, por el que se aprueba el {rd_365_1995_nombre}}"
|
||||||
|
]],
|
||||||
|
"rd_4_2010_ley" : ["plain", "{RD} 4/2010{rand:|, de 8 de Enero}"],
|
||||||
|
"rd_4_2010_nombre" : ["plain", "por el que se regula el {eni_nombre} en el ámbito de la Administración Electrónica"],
|
||||||
|
"rd_4_2010" : ["rand", [
|
||||||
|
"{rd_4_2010_nombre}",
|
||||||
|
"{rd_4_2010_ley}{rand:|, por el que se aprueba el {rd_4_2010_nombre}}"
|
||||||
|
]],
|
||||||
|
|
||||||
|
"rdl_2_2015_ley" : ["plain", "{RDL} 2/2015{rand:|, de 23 de Octubre}"],
|
||||||
|
"rdl_2_2015_nombre" : ["plain", "Texto Refundido de la Ley del Estatuto de los Trabajadores"],
|
||||||
|
"rdl_2_2015" : ["rand", [
|
||||||
|
"{rdl_2_2015_nombre}",
|
||||||
|
"{rdl_2_2015_ley}{rand:|, por el que se aprueba el {rdl_2_2015_nombre}}",
|
||||||
|
"{rand:|Ley del }Estatuto de los Trabajadores"
|
||||||
|
]],
|
||||||
|
|
||||||
|
"l_30_1984_ley" : ["plain", "Ley 30/1984{rand:|, de 2 de Agosto}"],
|
||||||
|
"l_30_1984_nombre" : ["plain", "Ley de Medidas para la Reforma de la Función Pública"],
|
||||||
|
"l_30_1984" : ["rand", [
|
||||||
|
"{l_30_1984_nombre}",
|
||||||
|
"{l_30_1984_ley}{rand:|, de Medidas para la Reforma de la Función Pública}"
|
||||||
|
]],
|
||||||
|
"l_53_1984_ley" : ["plain", "Ley 53/1984{rand:|, de 26 de Diciembre}"],
|
||||||
|
"l_53_1984_nombre" : ["plain", "Ley de Incompatibilidades del Personal al servicio de las Administraciones Públicas"],
|
||||||
|
"l_53_1984" : ["rand", [
|
||||||
|
"{l_53_1984_nombre}",
|
||||||
|
"{l_53_1984_ley}{rand:|, de Incompatibilidades del Personal al servicio de las Administraciones Públicas}"
|
||||||
|
]],
|
||||||
|
"l_11_2007_ley" : ["plain", "Ley 11/2007{rand:|, de 22 de Junio}"],
|
||||||
|
"l_11_2007_nombre" : ["plain", "Ley de Acceso Electrónico de los Ciudadanos a los Servicios Públicos"],
|
||||||
|
"l_11_2007" : ["rand", [
|
||||||
|
"{l_11_2007_nombre}",
|
||||||
|
"{l_11_2007_ley}{rand:|, de Acceso Electrónico de los Ciudadanos a los Servicios Públicos}"
|
||||||
|
]],
|
||||||
|
"l_39_2015_ley" : ["plain", "Ley 39/2015{rand:|, de 1 de Octubre}"],
|
||||||
|
"l_39_2015_nombre" : ["plain", "Ley del Procedimiento Administrativo Común de las Administraciones Públicas"],
|
||||||
|
"l_39_2015" : ["rand", [
|
||||||
|
"{l_39_2015_nombre}",
|
||||||
|
"{l_39_2015_ley}{rand:|, de Procedimiento Administrativo Común de las Administraciones Públicas}"
|
||||||
|
]],
|
||||||
|
"l_40_2015_ley" : ["plain", "Ley 40/2015{rand:|, de 1 de Octubre}"],
|
||||||
|
"l_40_2015_nombre" : ["plain", "Ley de Régimen Jurídico del Sector Público"],
|
||||||
|
"l_40_2015" : ["rand", [
|
||||||
|
"{l_40_2015_nombre}",
|
||||||
|
"{l_40_2015_ley}{rand:|, de Régimen Jurídico del Sector Público}"
|
||||||
|
]],
|
||||||
|
|
||||||
|
"lo_2_1986_ley" : ["plain", "{LO} 2/1986{rand:|, de 13 de marzo}"],
|
||||||
|
"lo_2_1986_nombre" : ["plain", "Ley Orgánica de Fuerzas y Cuerpos de Seguridad"],
|
||||||
|
"lo_2_1986" : ["rand", [
|
||||||
|
"{lo_2_1986_nombre}",
|
||||||
|
"{lo_2_1986_ley}{rand:|, de Fuerzas y Cuerpos de Seguridad}"
|
||||||
|
]]
|
||||||
|
|
||||||
|
}
|
||||||
|
}]
|
||||||
302
Public/json/kyman/especifico/kyman.ab.eni.json
Normal file
302
Public/json/kyman/especifico/kyman.ab.eni.json
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
[{
|
||||||
|
"origin" : "KyMAN",
|
||||||
|
"sources" : [
|
||||||
|
"https://administracionelectronica.gob.es/ctt/verPestanaGeneral.htm?idIniciativa=eni",
|
||||||
|
"https://administracionelectronica.gob.es/pae_Home/pae_Estrategias/pae_Interoperabilidad_Inicio/pae_Esquema_Nacional_de_Interoperabilidad.html"
|
||||||
|
],
|
||||||
|
"title" : "Informática - ENI",
|
||||||
|
"group" : "kyman_informatica_entornos_eni",
|
||||||
|
"group_variables" : {
|
||||||
|
"entidades" : ["select", [1, 5], "y", [
|
||||||
|
"{gobierno}", "Sector Público", "normalización", "regulación", "Administración Electrónica",
|
||||||
|
"Seguridad de la Información", "Redes de Comunicaciones", "Protección de Datos",
|
||||||
|
"Servicios en la Nube", "Ciberseguridad"
|
||||||
|
]],
|
||||||
|
"ONG" : ["rand", ["ONG", "Organizaciones No Gubernamentales"]],
|
||||||
|
"articulo_156" : ["plain", "comprende el conjunto de {mix:y,criterios|recomendaciones} en materia de {mix:y,seguridad|conservación|normalización} {mix:y,de la información|de los formatos|de las aplicaciones} que deberán ser tenidos en cuenta por las Administraciones Públicas para la toma de decisiones tecnológicas que garanticen operatibilidad"],
|
||||||
|
"leyes_mal_ley" : ["rand", [
|
||||||
|
"{rd_4_2010_ley}", "{l_11_2007_ley}", "{l_40_2015_ley}", "{l_30_1984_ley}", "{l_53_1984_ley}",
|
||||||
|
"{lo_2_1986_ley}", "{rdl_2_2015_ley}", "{d_315_1964_ley}", "{rd_364_1995_ley}", "{rd_365_1995_ley}"
|
||||||
|
]],
|
||||||
|
"leyes_mal_nombre" : ["rand", [
|
||||||
|
"{rd_4_2010_nombre}", "{l_11_2007_nombre}", "{l_40_2015_nombre}", "{l_30_1984_nombre}", "{l_53_1984_nombre}",
|
||||||
|
"{lo_2_1986_nombre}", "{rdl_2_2015_nombre}", "{d_315_1964_nombre}", "{rd_364_1995_nombre}", "{rd_365_1995_nombre}"
|
||||||
|
]],
|
||||||
|
"leyes_mal" : ["rand", [
|
||||||
|
"{leyes_mal_nombre}",
|
||||||
|
"{leyes_mal_ley}{rand:|, {leyes_mal_nombre}}"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"queries" : [{
|
||||||
|
"question" : "¿Qué es el {rand:ENI|{RD} 4/2010{rand:|, de 8 de Enero}}?",
|
||||||
|
"rights" : [
|
||||||
|
"Esquema Nacional de Interoperabilidad.",
|
||||||
|
"Un conjunto de {mix:y,principios|recomendaciones} para garantizar la interoperabilidad entre las Administraciones Públicas{rand:| Españolas}.",
|
||||||
|
"Establece los {mix:y,principios|directrices} de interoperabilidad en el {mix:y,intercambio|conservación} de la información electrónica por parte de Administraciones Públicas{rand:| Españolas}."
|
||||||
|
],
|
||||||
|
"wrongs" : [
|
||||||
|
"Un {OS} utilizado por las Administraciones Públicas{rand:| Españolas}.",
|
||||||
|
"Un protocolo de comunicación entre dispositivos electrónicos{rand:| utilizado en las Administraciones Públicas{rand:| Españolas}}.",
|
||||||
|
"Una {VPN} para empleados públicos{rand:| en el marco de las Administraciones Públicas{rand:| Españolas}}."
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Para quién va dirigido el {ENI}?",
|
||||||
|
"own_variables" : {
|
||||||
|
"seleccion_incorrecta" : ["Select", [1, 4], "y", [
|
||||||
|
"las Entidades Privadas que colaboren con las Administraciones Públicas{rand:| Españolas}",
|
||||||
|
"las Empresas Tecnológicas que provean servicios a las Administraciones Públicas{rand:| Españolas}",
|
||||||
|
"los Ciudadanos que interactúen con las Administraciones Públicas{rand:| Españolas}",
|
||||||
|
"las {ONG} que trabajen con las Administraciones Públicas{rand:| Españolas}",
|
||||||
|
"la Administración General del Estado",
|
||||||
|
"las Comunidades Autónomas",
|
||||||
|
"las Provincias",
|
||||||
|
"las {rand:Entidades|Administraciones} Locales",
|
||||||
|
"las Autoridades{rand:| Competentes}",
|
||||||
|
"{mix:y,los Cuerpos|las Fuerzas} de Seguridad{rand:| del Estado}",
|
||||||
|
"las Administraciones Públicas",
|
||||||
|
"la Ciudadanía"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"rights" : [
|
||||||
|
"Para todas las Administraciones Públicas{rand:| Españolas}.",
|
||||||
|
"Para los {mix:y,organismos|entidades} del sector público{rand:| Español}."
|
||||||
|
],
|
||||||
|
"wrongs" : ["{rand:Sólo p|Únicamente p|P}ara {seleccion_incorrecta}."]
|
||||||
|
}, {
|
||||||
|
"own_variables" : {
|
||||||
|
"lista_correcta" : ["list", [
|
||||||
|
"el Ministerio para la Transformación Digital y la Función Pública",
|
||||||
|
"la Secretaría del Estado de Función Pública",
|
||||||
|
"la Secretaría General de Administración Digital"
|
||||||
|
]],
|
||||||
|
"seleccion_incorrecta" : ["Select", [1, 4], "y", [
|
||||||
|
"list:lista_correcta",
|
||||||
|
"la Delegación de la Junta Autonómica delegada para la Transformación Digital",
|
||||||
|
"la Delegación Provincial destinada a la Transformación Digital",
|
||||||
|
"las Entidades Locales de {select:1-3,y,Gran Población|participantes en la Red SARA|con capacidad para Ventanilla Única}",
|
||||||
|
"los Órganos Empresariales que requieran comunicación con el Estado{rand:| Español}",
|
||||||
|
"las Entidades {select:1-2,y,Jurídicas|Físicas} que quieran operar en el Estado{rand:| Español}"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"question" : "¿Quiénes son los responsables del {ENI}{rand:| en cada Administración Pública}?",
|
||||||
|
"rights" : ["{Mix:y,list:lista_correcta}."],
|
||||||
|
"wrongs" : [
|
||||||
|
"No hay un responsable {rand:específico|designado|único}{rand:|, depende del ámbito donde se encuentre su marco de aplicación|, depende de cada Comunidad Autónoma}.",
|
||||||
|
"{seleccion_incorrecta}."
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué tipo de solución es el {ENI}?",
|
||||||
|
"rights" : ["Regulación."],
|
||||||
|
"wrongs" : ["{Select:1-5,y,Red de comunicaciones|Plataforma de servicios|Aplicación web|Software|Hardware|Protocolo de comunicación|Intranet de Seguridad|Ley{rand:| Orgánica}|Estatuto|Impositivo}."]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué relación tiene el {ENI} con el {ENS}?",
|
||||||
|
"rights" : [
|
||||||
|
"Ambos son Esquemas Nacionales que regulan aspectos diferentes pero complementarios en la Administración Electrónica.",
|
||||||
|
"El {ENI} se centra en la interoperabilidad, mientras que el {ENS} se enfoca en la seguridad de los sistemas de información."
|
||||||
|
],
|
||||||
|
"wrongs" : [
|
||||||
|
"{Mix:y,el {ENI}|el {ENS}} son lo mismo, ambos regulan la seguridad en la Administración Electrónica{rand:| dentro del marco de las Administraciones Públicas{rand:| Españolas}}.",
|
||||||
|
"El {ENI} es una versión anterior del {ENS}, y ha sido reemplazado por este último.",
|
||||||
|
"No tienen ninguna relación, ya que uno es para {mix:y,la Administración Pública|el otro para empresas privadas}.",
|
||||||
|
"No tienen ninguna relación entre sí pues abordan temas completamente diferentes{rand:|: mientras uno se centra en el ámbito de {rand:la Seguridad|la Segmentación|los Servicios|los Servidores}, el otro se centra en la {rand:Intranet|Internet|Interoperabilidad}.}"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué normativa complementa al {rand:ENI|Esquema Nacional de Interoperabilidad} en materia de interoperabilidad?",
|
||||||
|
"rights" : ["{RD} 4/2010{rand:|, de 8 de Enero}{rand:|, por el que se regula el Esquema Nacional de Interoperabilidad en el ámbito de la Administración Electrónica}."],
|
||||||
|
"wrongs" : [
|
||||||
|
"{rand:{RD_RDL}|Ley{rand:| Orgánica}} {rand:4/2010|311/2022}{rand:|, de {rand:8|2} de {rand:Enero|Mayo}}{rand:|, por el que se regula el Esquema Nacional de Seguridad}.",
|
||||||
|
"{rand:{RD_RDL}|Ley{rand:| Orgánica}} {ley_base}{rand:|, por la que se regula el Esquema Nacional de {select:1-2,y,Seguridad|Interoperabilidad}}."
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Cuál es el estado actual del {ENI}?",
|
||||||
|
"rights" : ["En producción."],
|
||||||
|
"wrongs" : [
|
||||||
|
"En desarrollo.",
|
||||||
|
"En fase de pruebas.",
|
||||||
|
"Obsoleto.",
|
||||||
|
"En revisión.",
|
||||||
|
"En periodo de aplicación{rand:| provisional| voluntaria}."
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Cuál es el área orgánica del {ENI}?",
|
||||||
|
"rights" : "Estatal.",
|
||||||
|
"wrongs" : ["Autonómica.", "Local.", "Privada.", "Mixta.", "Provincial.", "Internacional.", "Intereuropea."]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Cuál es el ámbito funcional del {ENI}?",
|
||||||
|
"rights" : ["Administración Electrónica."],
|
||||||
|
"wrongs" : ["{Cap:{entidades}}."]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Cuál es el área técnica del {ENI}?",
|
||||||
|
"rights" : ["{Mix:y,normalización|regulación}."],
|
||||||
|
"wrongs" : ["{Cap:{entidades}}."]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Cuál es el área funcional del {ENI}?",
|
||||||
|
"rights" : ["{Mix:y,{gobierno}|Sector Público}."],
|
||||||
|
"wrongs" : ["{Cap:{entidades}}."]
|
||||||
|
}, {
|
||||||
|
"own_variables" : {
|
||||||
|
"respuesta_falsa" : ["Select", [1, 4], "y", [
|
||||||
|
"proporcionar un marco legal para la creación de nuevas tecnologías en el ámbito público",
|
||||||
|
"regular el uso de tecnologías específicas en las Administraciones Públicas{rand:| Españolas}",
|
||||||
|
"establecer un sistema de seguridad para proteger los datos de los ciudadanos en las Administraciones Públicas{rand:| Españolas}",
|
||||||
|
"crear una red de comunicaciones exclusiva para las Administraciones Públicas{rand:| Españolas}"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"question" : "¿Cuál es la motivación por la cual se creó el {ENI}?",
|
||||||
|
"rights" : ["Ofrecer a los ciudadanos {mix:y,fluidez|eficacia|eficiencia} para garantizarles los {mix:y,derechos|principios}{rand:| mediante la cooperación entre las administraciones{rand:| con {mix:y,el desarrollo|la prestación|el despliegue} de servicios públicos}}."],
|
||||||
|
"wrongs" : ["{respuesta_falsa}."]
|
||||||
|
}, {
|
||||||
|
"own_variables" : {
|
||||||
|
"articulos_incorrectos" : ["rand", [
|
||||||
|
"Objeto", "Ámbito Subjetivo", "Principios Generales",
|
||||||
|
"Principios de intervención de las Administraciones Públicas para el desarrollo de una actividad"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"question" : "¿Qué artículo de la {l_40_2015} incluye a la Interoperabilidad como principio de actuación de las Administraciones Públicas?",
|
||||||
|
"rights" : ["El artículo 3{rand:|, Principios Generales}."],
|
||||||
|
"wrongs" : ["El artículo {range:1-23}{rand:|, {articulos_incorrectos}}."]
|
||||||
|
}, {
|
||||||
|
"own_variables" : {
|
||||||
|
"garantias" : ["mix", "y", [
|
||||||
|
"la {mix:y,interoperabilidad|seguridad} de {mix:y,los sistemas|las soluciones} adoptados por cada una de ellas",
|
||||||
|
"la protección de los datos de carácter personal",
|
||||||
|
"el facilitar preferentemente la prestación conjunta de servicios a los interesados"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"question" : "¿Qué nos dice el principio de actuación{rand:| en el artículo 3{rand:|, Principios Generales}} de la {l_40_2015}?",
|
||||||
|
"rights" : ["Las Administraciones Públicas estarán relacionadas entre sí a través de medios electrónicos{rand: que {rand:|garanticen|aseguren}|, {rand:asegurando|garantizando}} {garantias}."],
|
||||||
|
"wrongs" : ["Las Administraciones Públicas {rand:{rand:deberían|podrán}|estarán relacionadas entre sí a través de} utilizar medios electrónicos{rand: que {rand:|garanticen|aseguren}|, {rand:asegurando|garantizando}, sin necesidad de garantizar} {select:1-2,y,la interoperabilidad|la seguridad de los datos}{rand:| si así lo consideran oportuno| únicamente}."]
|
||||||
|
}, {
|
||||||
|
"own_variables" : {
|
||||||
|
"articulos_incorrectos" : ["rand", [
|
||||||
|
"Transparencia de tecnología entre Administraciones",
|
||||||
|
"Reutilización de {select:1-2,y,sistemas|aplicaciones} de propiedad de la Administración",
|
||||||
|
"{select:1-2,y,{eni_nombre}|{ens_nombre}}",
|
||||||
|
"Transmisiones de datos entre Administraciones Públicas"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"question" : "¿Qué artículo de la {l_40_2015} {articulo_156}?",
|
||||||
|
"rights" : "El artículo 156{rand:|, {mix:y,{eni_nombre}|{ens_nombre}}}.",
|
||||||
|
"wrongs" : ["El artículo {rand:{range:155-158}|{range:1-300}}{rand:|, {articulos_incorrectos}}."]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué nos dice el artículo 156{rand:|, {mix:y,{eni_nombre}|{ens_nombre}}} de la {l_40_2015}?",
|
||||||
|
"rights" : ["{Cap:{articulo_156}}."],
|
||||||
|
"wrongs" : [
|
||||||
|
"Establece que las Administraciones Públicas deben utilizar medios electrónicos para garantizar la interoperabilidad entre ellas.",
|
||||||
|
"Regula la creación de nuevas tecnologías en el ámbito público.",
|
||||||
|
"Establece un sistema de seguridad para proteger los datos de los ciudadanos en las Administraciones Públicas{rand:| Españolas}.",
|
||||||
|
"Crea una red de comunicaciones exclusiva para las Administraciones Públicas{rand:| Españolas}.",
|
||||||
|
"Comprende el conjunto de {select:1-3,y,criterios|recomendaciones|malas prácticas} en materia de {select:1-5,y,seguridad|conservación|normalización|digitalización|codificación|encriptación} {mix:y,de la información|de los formatos|de las aplicaciones} que deberán ser evitados por las Administraciones Públicas para la toma de decisiones tecnológicas que garanticen operatibilidad."
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"own_variables" : {
|
||||||
|
"articulos_incorrectos" : ["rand", [
|
||||||
|
"Interoperabilidad de los Sistemas de Información",
|
||||||
|
"{mix:y,{eni_nombre}|{ens_nombre}}",
|
||||||
|
"Red de comunicaciones de las Administraciones Públicas españolas",
|
||||||
|
"Red integrada de Atención al Ciudadano"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"question" : "¿En dónde fue establecido el {ENI} originalmente?",
|
||||||
|
"rights" : ["En el artículo {rand:42|{mix:y,{eni_nombre}|{ens_nombre}}} de la {l_11_2007}."],
|
||||||
|
"wrongs" : ["En el artículo {rand:{range:41-44}|{range:1-60}|{articulos_incorrectos}} {rand:de la {rand:{l_11_2007}|{l_40_2015}}|del {rd_4_2010}}."]
|
||||||
|
}, {
|
||||||
|
"question" : "¿En dónde fue materializado el {ENI}?",
|
||||||
|
"rights" : ["En {rd_4_2010}."],
|
||||||
|
"wrongs" : ["En {leyes_mal}."]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Cuál es la finalidad de las {NTI} del {ENI}?",
|
||||||
|
"rights" : ["Concretar detalles para facilitar los aspectos más {mix:y,prácticos|operativos} de la interoperabilidad {mix:y,entre las Administraciones Públicas|con el ciudadano}."],
|
||||||
|
"wrongs" : [
|
||||||
|
"Establecer un marco legal para la creación de nuevas tecnologías en el ámbito público.",
|
||||||
|
"Regular el uso de tecnologías específicas {select:1-2,y,entre las Administraciones Públicas{rand: Españolas}|con los ciudadanos}.",
|
||||||
|
"Establecer un sistema de seguridad para proteger los datos de los ciudadanos en las Administraciones Públicas{rand: Españolas}.",
|
||||||
|
"Crear una red de comunicaciones exclusiva para las Administraciones Públicas{rand: Españolas}."
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Quién desarrolló el {ENI}?",
|
||||||
|
"rights" : ["El Ministerio de {mix:y,Política Territorial|Función Pública}."],
|
||||||
|
"wrongs" : [
|
||||||
|
"El Ministerio de {select:1-3,y,Seguridad|Defensa|de Transición Tecnológica}.",
|
||||||
|
"La Agencia Española de Protección de Datos.",
|
||||||
|
"El Instituto Nacional de Ciberseguridad.",
|
||||||
|
"La Secretaría de Estado de Digitalización e Inteligencia Artificial."
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Cuáles son los objetivos del {ENI}?",
|
||||||
|
"own_variables" : {
|
||||||
|
"objetivos" : ["lista", [
|
||||||
|
"comprender {mix:y,los criterios|las recomendaciones}",
|
||||||
|
"proporcionar los elementos",
|
||||||
|
"facilitar la implantación de las políticas de seguridad"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"rights" : ["{Mix:y,list:objetivos}."],
|
||||||
|
"wrongs" : ["{Select:1-5,y,list:objetivos|garantizar conectivdad entre los sectores {mix:y,público|privado}|establecer un sistema de seguridad para proteger los datos de los ciudadanos|crear una red de comunicaciones exclusiva para las Administraciones Públicas}."]
|
||||||
|
}, {
|
||||||
|
"question" : "¿Cuáles son los elementos principales del {eni_nombre}?",
|
||||||
|
"own_variables" : {
|
||||||
|
"elementos" : ["list", [
|
||||||
|
"los principios básicos de la interoparagerabilidad",
|
||||||
|
"la interoperabilidad organizativa",
|
||||||
|
"la interoperabilidad semántica",
|
||||||
|
"la interoperabilidad técnica",
|
||||||
|
"{mix:y,las infraestructuras|los servicios} comunes",
|
||||||
|
"la utilización, preferiblemente, de la Red de comunciaciones de las Administraciones Públicas",
|
||||||
|
"la reutilización",
|
||||||
|
"la interoperabilidad {mix:y,de la firma electrónica|de los certificados}",
|
||||||
|
"la {mix:y,recuperación|conservación} del documento electrónico",
|
||||||
|
"las normas técnicas de interoperabilidad"
|
||||||
|
]],
|
||||||
|
"elementos_mal" : ["list", [
|
||||||
|
"la creación de nuevas tecnologías en el ámbito público",
|
||||||
|
"el uso de tecnologías específicas en las Administraciones Públicas",
|
||||||
|
"el establecimiento de un sistema de seguridad para proteger los datos de los ciudadanos",
|
||||||
|
"la creación de una red de comunicaciones exclusiva para las Administraciones Públicas",
|
||||||
|
"la implementación de software propietario en las Administraciones Públicas",
|
||||||
|
"la centralización de todos los datos en un único servidor nacional",
|
||||||
|
"la eliminación de la interoperabilidad entre diferentes sistemas",
|
||||||
|
"la reducción de la seguridad en los sistemas de información",
|
||||||
|
"la limitación del acceso a los servicios públicos digitales",
|
||||||
|
"la desactualización tecnológica de las infraestructuras públicas",
|
||||||
|
"la falta de formación del personal público en tecnologías de la información"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"rights" : ["{Mix:y,list:elementos}."],
|
||||||
|
"wrongs" : ["{Select:1-12,y,list:elementos|list:elementos_mal}."]
|
||||||
|
}, {
|
||||||
|
"own_variables" : {
|
||||||
|
"leyes_mal" : ["select", [1, 4], "y", [
|
||||||
|
"de la {l_39_2015}",
|
||||||
|
"de la {l_40_2015}",
|
||||||
|
"del {rd_4_2010}",
|
||||||
|
"de la {l_53_1984}",
|
||||||
|
"de la {l_30_1984}",
|
||||||
|
"de la {l_11_2007}",
|
||||||
|
"de la {lo_2_1986}"
|
||||||
|
]],
|
||||||
|
"bien" : ["list", [
|
||||||
|
"el ámbito subjetivo",
|
||||||
|
"lo indicado sobre el sector público institucional"
|
||||||
|
]],
|
||||||
|
"mal" : ["list", [
|
||||||
|
"el ámbito territorial",
|
||||||
|
"lo indicado sobre el área orgánica"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"question" : "¿En dónde se establece el ámbito de aplicación del {ENI}?",
|
||||||
|
"rights" : ["En el artículo 2 de {mix:y,la {l_39_2015}|la {l_40_2015}}{rand:|, sobre {mix:y,list:bien}}."],
|
||||||
|
"wrongs" : ["En {rand:el artículo {rand:{range:1-100}}|los artículos {select:1-5,y,{serie:1-100}|{serie:1-100}|{serie:1-100}|{serie:1-100}|{serie:1-100}}} {leyes_mal}{rand:|, sobre {mix:y,list:bien|list:mal}}."]
|
||||||
|
}, {
|
||||||
|
"own_variables" : {
|
||||||
|
"categorias" : ["list", [
|
||||||
|
"marco organizativo",
|
||||||
|
"marco operacional",
|
||||||
|
"medidas técnicas"
|
||||||
|
]]
|
||||||
|
},
|
||||||
|
"question" : "¿Cuáles son las categorías por las que se fundamenta la adecuación del {ENI}?",
|
||||||
|
"rights" : ["{Mix:y,list:categorias}."],
|
||||||
|
"wrongs" : ["{Select:1-5,y,list:categorias|marco legal|marco financiero|marco estratégico|marco tecnológico|marco social}."]
|
||||||
|
}]
|
||||||
|
}]
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
[{
|
||||||
|
"origin" : "KyMAN",
|
||||||
|
"sources" : [
|
||||||
|
"https://administracionelectronica.gob.es/ctt/verPestanaGeneral.htm?idIniciativa=eni",
|
||||||
|
"https://administracionelectronica.gob.es/pae_Home/pae_Estrategias/pae_Interoperabilidad_Inicio/pae_Esquema_Nacional_de_Interoperabilidad.html",
|
||||||
|
"https://administracionelectronica.gob.es/dam/jcr:85ca4b29-f229-413c-a533-a290bdb7bec6/ENI_Preguntas_frecuentes.pdf",
|
||||||
|
"https://administracionelectronica.gob.es/pae_Home/dam/jcr:c00307e0-1337-4b25-9728-d101c059cd3a/20131208_ENI_Preguntas_frecuentes.pdf"
|
||||||
|
],
|
||||||
|
"title" : "Informática - ENI - Preguntas Frecuentes",
|
||||||
|
"group" : "kyman_informatica_entornos_eni",
|
||||||
|
"group_variables" : {},
|
||||||
|
"queries" : [{
|
||||||
|
"question" : "¿Qué es el {ENI}?",
|
||||||
|
"rights" : [
|
||||||
|
"El {rd_4_2010}, regula el citado Esquema previsto en el artículo 156 de la {l_40_2015}, que sustituye al apartado 1 del artículo 42 de la {l_11_2007}.",
|
||||||
|
"Comprende el conjunto de {mix:y,criterios|recomendaciones} que deberían ser tenidos en cuenta por las {AAPP} para la toma de decisiones tecnológicas que garanticen la interoperabilidad.",
|
||||||
|
"La cooperación entre las {AAPP} es esencial para proporcionar los servicios a los ciudadanos y garantizarles su derecho a relacionarse electrónicamente con ellas. Dicha cooperación requiere unas condiciones tales que permitan que la misma se pueda llevar a cabo con fluidez, para lo cual es necesario que haya interoperabilidad.",
|
||||||
|
"El Esquema persigue la creación de las condiciones necesarias para garantizar nivel de interoperabilidad {mix:y,técnica|semántica|organizativa} de {mix:y,los sistemas|las aplicaciones} empleados por las {AAPP}, que permitan {mix:y,el ejercicio de los derechos|el cumplimiento de los deberes} a través del acceso electrónico a los servicios públicos, a la vez que redunda en beneficio de {mix:y,la eficacia|la eficiencia}.",
|
||||||
|
"Es el marco legal y técnico que define las normas para que los sistemas de información de las distintas {AAPP} españolas puedan comunicarse e intercambiar datos entre sí.",
|
||||||
|
"Un conjunto de criterios y recomendaciones (técnicos, semánticos y organizativos) que aseguran que las aplicaciones informáticas del sector público sean compatibles.",
|
||||||
|
"La normativa, recogida en el {rd_4_2010}, que permite la cooperación entre {AAPP} a nivel digital, facilitando la vida al ciudadano.",
|
||||||
|
"Es la estrategia del Estado para evitar que cada organismo público ({select:1-3,y,ministerios|ayuntamientos|{CCAA}|provincias} entre otros) desarrolle sistemas aislados que no pueden 'hablar' entre ellos.",
|
||||||
|
"Una pieza clave de la Administración electrónica que garantiza, por ejemplo, que un ciudadano no tenga que presentar un documento en un organismo si este ya obra en poder de otro.",
|
||||||
|
"Define los estándares comunes (como {mix:o,formatos de documento|firma electrónica|modelos de datos}) que debe usar el sector público para garantizar la compatibilidad."
|
||||||
|
],
|
||||||
|
"wrongs" : [
|
||||||
|
"El {rand:{rd_4_2010}|{rdl_2_2015}|{d_315_1964}|{rd_364_1995}|{rd_365_1995}}, regula el citado Esquema previsto en el artículo {range:1-200} de la {rand:{l_11_2007}|{l_40_2015}|{l_30_1984}|{l_53_1984}}, que sustituye al apartado {range:1-7} del artículo {range:1-200} de la {rand:{l_11_2007}|{l_40_2015}|{l_30_1984}|{l_53_1984}}.",
|
||||||
|
"Es un conjunto de normas jurídicas que regulan la seguridad de los sistemas de información de las {AAPP}.",
|
||||||
|
"Es un marco normativo que establece los requisitos mínimos de seguridad para los sistemas de información de las {AAPP}.",
|
||||||
|
"Es un conjunto de directrices para la gestión de la seguridad de la información en las {AAPP}.",
|
||||||
|
"Es el {ENS}, una normativa complementaria que establece las medidas de índole {select:1-2,y,técnica|organizativa} necesarias para proteger los sistemas de información de ciberataques, robos de datos y otras amenazas digitales.",
|
||||||
|
"Una directiva de la {EU}, de obligado cumplimiento para todos los estados miembros, que regula {select:1-3,y,el mercado único digital|el comercio electrónico transfronterizo|la portabilidad de servicios de streaming} entre países.",
|
||||||
|
"Un programa de software específico, similar a {select:1-2,o,un {OS}|un antivirus avanzado}, que el {rand:{gobierno}|Gobierno central} obliga a instalar en todos los servidores de las {AAPP} para centralizar la gestión de las bases de datos.",
|
||||||
|
"El organismo público, dependiente del Ministerio de {select:1-2,y,Asuntos Económicos|Transformación Digital}, que se encarga de gestionar {select:1-3,y,la red de fibra óptica nacional|{Red_SARA}|de auditar la ciberseguridad de las entidades{rand:| {select:1-3,y,locales|nacionales|provinciales|autonómicas|estatales|públicas|privadas}}}.",
|
||||||
|
"El {rgpd} en España, enfocada exclusivamente en {select:1-2,y,la privacidad del ciudadano|el derecho al olvido}.",
|
||||||
|
"Un plan del {gobierno} para fomentar la internacionalización de las empresas tecnológicas españolas, facilitando su expansión a mercados latinoamericanos.",
|
||||||
|
"El portal web oficial donde los ciudadanos pueden {select:1-2,y,consultar todas las leyes publicadas en el {BOE}|acceder al Punto de Acceso General (administracion.gob.es) para realizar trámites}."
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}]
|
||||||
10
Public/json/kyman/especifico/kyman.ad.ens.json
Normal file
10
Public/json/kyman/especifico/kyman.ad.ens.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[{
|
||||||
|
"origin" : "KyMAN",
|
||||||
|
"sources" : [
|
||||||
|
"https://administracionelectronica.gob.es/pae_Home/pae_Estrategias/pae_Seguridad_Inicio/pae_Esquema_Nacional_de_Seguridad.html"
|
||||||
|
],
|
||||||
|
"title" : "Informática - ENS",
|
||||||
|
"group" : "kyman_informatica_entornos_ens",
|
||||||
|
"group_variables" : {},
|
||||||
|
"queries" : []
|
||||||
|
}]
|
||||||
@ -431,6 +431,7 @@
|
|||||||
"AI_DL" : ["rand", ["DL", "Deep Learning", "Aprendizaje Profundo"]],
|
"AI_DL" : ["rand", ["DL", "Deep Learning", "Aprendizaje Profundo"]],
|
||||||
"AI_CV" : ["rand", ["CV", "Computer Vision", "Visión por Computadora"]],
|
"AI_CV" : ["rand", ["CV", "Computer Vision", "Visión por Computadora"]],
|
||||||
"AI_RL" : ["rand", ["RL", "Reinforcement Learning", "Aprendizaje por Refuerzo"]],
|
"AI_RL" : ["rand", ["RL", "Reinforcement Learning", "Aprendizaje por Refuerzo"]],
|
||||||
|
"TTL" : ["rand", ["TTL", "Time to Live", "Tiempo de Vida"]],
|
||||||
|
|
||||||
"broadcast" : ["rand", ["Broadcast", "Difusión"]],
|
"broadcast" : ["rand", ["Broadcast", "Difusión"]],
|
||||||
"multicast" : ["rand", ["Multicast", "Multidifusión"]],
|
"multicast" : ["rand", ["Multicast", "Multidifusión"]],
|
||||||
@ -470,6 +471,40 @@
|
|||||||
"Red_SARA_a" : ["rand", ["a la Red SARA", "al Sistema de Aplicaciones y Redes para las Administraciones"]],
|
"Red_SARA_a" : ["rand", ["a la Red SARA", "al Sistema de Aplicaciones y Redes para las Administraciones"]],
|
||||||
"Red_IA" : ["rand", ["Red IA", "Intranet Administrativa"]],
|
"Red_IA" : ["rand", ["Red IA", "Intranet Administrativa"]],
|
||||||
"sTESTA" : ["rand", ["sTESTA", "Secured Trans European Services for Telematics between Administrations", "Servicios Telemáticos Seguros Trans Europeos entre Administraciones"]],
|
"sTESTA" : ["rand", ["sTESTA", "Secured Trans European Services for Telematics between Administrations", "Servicios Telemáticos Seguros Trans Europeos entre Administraciones"]],
|
||||||
"RedIRIS" : ["rand", ["RedIRIS", "Red de la Infraestructura de Investigación y Educación Española"]]
|
"RedIRIS" : ["rand", ["RedIRIS", "Red de la Infraestructura de Investigación y Educación Española"]],
|
||||||
|
|
||||||
|
"ENI" : ["rand", ["ENI", "Esquema Nacional de Interoperabilidad", "{RD} 4/2010{rand:|, de 8 de Enero}{rand:|, por el que se regula el Esquema Nacional de Interoperabilidad en el ámbito de la Administración Electrónica}"]],
|
||||||
|
"ENS" : ["rand", ["ENS", "Esquema Nacional de Segridad", "{RD} 311/2022{rand:|, de 2 de Mayo}{rand:|, por el que se regula el Esquema Nacional de Seguridad}"]],
|
||||||
|
"NTI" : ["rand", ["NTI", "Norma Técnica de Interoperabilidad"]],
|
||||||
|
|
||||||
|
"osi1" : ["rand", [
|
||||||
|
"Capa {rand:de Física|1} del Modelo {OSI}",
|
||||||
|
"Capa {rand:de Acceso al Medio|del Medio|1} del Modelo {TCP_IP}"
|
||||||
|
]],
|
||||||
|
"osi2" : ["rand", [
|
||||||
|
"Capa {rand:de Enlace{rand:| de Red}|2} del Modelo {OSI}",
|
||||||
|
"Capa {rand:de Acceso al Medio|del Medio|1} del Modelo {TCP_IP}"
|
||||||
|
]],
|
||||||
|
"osi3" : ["rand", [
|
||||||
|
"Capa {rand:de Red|3} del Modelo {OSI}",
|
||||||
|
"Capa {rand:de Internet|Network|2} del Modelo {TCP_IP}"
|
||||||
|
]],
|
||||||
|
"osi4" : ["rand", [
|
||||||
|
"Capa {rand:de Transporte|4} del Modelo {OSI}",
|
||||||
|
"Capa {rand:de Transporte|3} del Modelo {TCP_IP}"
|
||||||
|
]],
|
||||||
|
"osi5" : ["rand", [
|
||||||
|
"Capa {rand:de Sesión|5} del Modelo {OSI}",
|
||||||
|
"Capa {rand:de Aplicación|4} del Modelo {TCP_IP}"
|
||||||
|
]],
|
||||||
|
"osi6" : ["rand", [
|
||||||
|
"Capa {rand:de Presentación|6} del Modelo {OSI}",
|
||||||
|
"Capa {rand:de Aplicación|4} del Modelo {TCP_IP}"
|
||||||
|
]],
|
||||||
|
"osi7" : ["rand", [
|
||||||
|
"Capa {rand:de Aplicación|7} del Modelo {OSI}",
|
||||||
|
"Capa {rand:de Aplicación|4} del Modelo {TCP_IP}"
|
||||||
|
]]
|
||||||
|
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
69
Public/json/kyman/especifico/software/kyman.00.ping.json
Normal file
69
Public/json/kyman/especifico/software/kyman.00.ping.json
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
[{
|
||||||
|
"origin" : "KyMAN",
|
||||||
|
"sources" : [],
|
||||||
|
"title" : "Software - Comando Ping",
|
||||||
|
"group" : "kyman_software_comando_ping",
|
||||||
|
"queries" : [{
|
||||||
|
"question" : "¿Qué es el comando ping?",
|
||||||
|
"rights" : [
|
||||||
|
"Es una herramienta de red utilizada para comprobar la conectividad entre dos dispositivos en una red {IP}.",
|
||||||
|
"Funciona enviando paquetes {ICMP} de solicitud de eco a la dirección {IP} de destino y esperando una respuesta de eco.",
|
||||||
|
"Mide el tiempo que tarda en recibir una respuesta, lo que ayuda {mix:y,a diagnosticar problemas de red|a determinar la latencia entre los dispositivos}.",
|
||||||
|
"Es comúnmente utilizado por {select:1-2,y,administradores de red|usuarios} para verificar si un host está {mix:y,accesible|funcionando correctamente}."
|
||||||
|
],
|
||||||
|
"wrongs" : [
|
||||||
|
"Es una herramienta de edición de texto utilizada para {select:1-2,y,crear|modificar} archivos de configuración de red.",
|
||||||
|
"Es un protocolo de seguridad utilizado para proteger las comunicaciones en redes inalámbricas.",
|
||||||
|
"Es una aplicación de monitoreo de red que proporciona estadísticas detalladas sobre el tráfico de datos en tiempo real."
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"question" : "¿En qué capa de red trabaja el comando ping?",
|
||||||
|
"rights" : ["En la {osi3}{rand:|, ya que utiliza el protocolo {ICMP} para {mix:y,enviar|recibir} mensajes entre dispositivos}."],
|
||||||
|
"wrongs" : [
|
||||||
|
"En la {osi7}, ya que se utiliza para {mix:y,interactuar con servicios de red|gestionar conexiones de red}.",
|
||||||
|
"En la {osi6}, ya que se encarga de la representación y codificación de datos para la transmisión.",
|
||||||
|
"En la {osi5}, ya que se encarga de la negociación de sesiones entre dispositivos en una red.",
|
||||||
|
"En la {osi4}, ya que se encarga de {select:1-2,y,la gestión de conexiones|el control de flujo} entre dispositivos.",
|
||||||
|
"En la {osi2}, ya que se encarga de la transmisión de datos entre dispositivos en una red local.",
|
||||||
|
"En la {osi1}, ya que se ocupa de la transmisión {select:1-2,o,de señales eléctricas|de radio} entre dispositivos."
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"origin" : "KyMAN",
|
||||||
|
"sources" : [],
|
||||||
|
"title" : "Software - Comando Ping",
|
||||||
|
"group" : "kyman_software_comando_ping",
|
||||||
|
"queries" : [{
|
||||||
|
"question" : "¿Qué hace el parámetro {rand:{rand:-|/}i en Windows|-t en Linux} en el comando ping?",
|
||||||
|
"rights" : ["Establece el {TTL}{rand:| de los paquetes enviados {ICMP}}."],
|
||||||
|
"brothers_are_wrongs" : true
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué hace el parámetro {rand:-|/}t en Windows en el comando ping?",
|
||||||
|
"rights" : ["Hace que el comando ping envíe paquetes {ICMP} de forma continua hasta que se interrumpa manualmente."],
|
||||||
|
"brothers_are_wrongs" : true
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué hace el parámetro {rand:{rand:-|/}n en Windows|-c en Linux} en el comando ping?",
|
||||||
|
"rights" : ["Especifica el número de paquetes {ICMP} que se enviarán durante la prueba de ping."],
|
||||||
|
"brothers_are_wrongs" : true
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué hace el parámetro {rand:{rand:-|/}l en Windows|-s en Linux} en el comando ping?",
|
||||||
|
"rights" : ["Especifica el tamaño, en bytes, de los paquetes {ICMP} que se enviarán."],
|
||||||
|
"brothers_are_wrongs" : true
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué hace el parámetro {rand:{rand:-|/}a en Windows|-a en Linux} en el comando ping?",
|
||||||
|
"rights" : ["Resuelve y muestra el nombre de host asociado a la dirección {IP} de destino."],
|
||||||
|
"brothers_are_wrongs" : true
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué hace el parámetro -4 en el comando ping?",
|
||||||
|
"rights" : ["Fuerza al comando ping a utilizar la {IPv4} para la comunicación."],
|
||||||
|
"brothers_are_wrongs" : true
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué hace el parámetro -6 en el comando ping?",
|
||||||
|
"rights" : ["Fuerza al comando ping a utilizar la {IPv6} para la comunicación."],
|
||||||
|
"brothers_are_wrongs" : true
|
||||||
|
}, {
|
||||||
|
"question" : "¿Qué hace el parámetro {rand:-|/}w en el comando ping?",
|
||||||
|
"rights" : ["Especifica el tiempo de espera, en milisegundos, para recibir una respuesta antes de considerar que el paquete se ha perdido."],
|
||||||
|
"brothers_are_wrongs" : true
|
||||||
|
}]
|
||||||
|
}]
|
||||||
25
Python/Abstracts/ControllersAbstract.py
Normal file
25
Python/Abstracts/ControllersAbstract.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Callable
|
||||||
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
|
from Models.RequestModel import RequestModel
|
||||||
|
|
||||||
|
class ControllersAbstract:
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
ot:OpoTestsInterface,
|
||||||
|
actions:dict[str, Callable[[RequestModel], tuple[Any|None, dict[str, Any|None]]]]
|
||||||
|
) -> None:
|
||||||
|
self.ot:OpoTestsInterface = ot
|
||||||
|
self.__actions:dict[str, Callable[[RequestModel], tuple[Any|None, dict[str, Any|None]]]] = actions
|
||||||
|
|
||||||
|
def add(self:Self, key:str, action:Callable[[RequestModel], tuple[Any|None, dict[str, Any|None]]], overwrite:bool = False) -> None:
|
||||||
|
if overwrite or key not in self.__actions:
|
||||||
|
self.__actions[key] = action
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
key:str,
|
||||||
|
request:RequestModel
|
||||||
|
) -> tuple[Any|None, dict[str, Any|None]]|None:
|
||||||
|
return self.__actions[key](request) if key in self.__actions else None
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from typing import Self, Any, Optional
|
from typing import Self, Any, Optional
|
||||||
from Managers.SettingsManager import SettingsManager
|
from Managers.SettingsManager import SettingsManager
|
||||||
@ -7,6 +8,12 @@ from Drivers.HTTPSocketDriver import HTTPSocketDriver
|
|||||||
from Drivers.FilesDriver import FilesDriver
|
from Drivers.FilesDriver import FilesDriver
|
||||||
from traceback import format_stack as trace_format_stack
|
from traceback import format_stack as trace_format_stack
|
||||||
from traceback import extract_tb as extract_traceback
|
from traceback import extract_tb as extract_traceback
|
||||||
|
from Managers.QuestionsManager import QuestionsManager
|
||||||
|
from Managers.UsersManager import UsersManager
|
||||||
|
from Modules.FormatModule import FormatModule
|
||||||
|
from Managers.ControllersManager import ControllersManager
|
||||||
|
from Managers.RoutesManager import RoutesManager
|
||||||
|
from Utils.Check import Check
|
||||||
from Utils.Patterns import RE
|
from Utils.Patterns import RE
|
||||||
from Utils.Utils import Utils
|
from Utils.Utils import Utils
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@ -16,6 +23,8 @@ class OpoTests:
|
|||||||
|
|
||||||
def __init__(self:Self, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None) -> None:
|
def __init__(self:Self, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None) -> None:
|
||||||
|
|
||||||
|
key:str
|
||||||
|
|
||||||
self.__print_format:str = "[{type}] {yyyy}{mm}{dd} {hh}{ii}{ss} [{line}]{file}({method}): {message}"
|
self.__print_format:str = "[{type}] {yyyy}{mm}{dd} {hh}{ii}{ss} [{line}]{file}({method}): {message}"
|
||||||
self.__exception_format:str = " '{file}({method})[{line}]'{lines}\n\n{exception_message}"
|
self.__exception_format:str = " '{file}({method})[{line}]'{lines}\n\n{exception_message}"
|
||||||
|
|
||||||
@ -27,10 +36,22 @@ class OpoTests:
|
|||||||
self.i18n:I18NManager = I18NManager(self)
|
self.i18n:I18NManager = I18NManager(self)
|
||||||
self.files:FilesDriver = FilesDriver(self)
|
self.files:FilesDriver = FilesDriver(self)
|
||||||
self.http_server:HTTPSocketDriver = HTTPSocketDriver(self)
|
self.http_server:HTTPSocketDriver = HTTPSocketDriver(self)
|
||||||
|
self.users:UsersManager = UsersManager(self)
|
||||||
|
self.questions:QuestionsManager = QuestionsManager(self)
|
||||||
|
self.format:FormatModule = FormatModule(self)
|
||||||
|
self.controllers:ControllersManager = ControllersManager(self)
|
||||||
|
self.routes:RoutesManager = RoutesManager(self)
|
||||||
|
|
||||||
self.http_server.start()
|
for key in ("settings", "i18n", "files", "users", "questions", "format", "controllers", "routes", "http_server"):
|
||||||
|
getattr(getattr(self, key), "start")()
|
||||||
|
|
||||||
def print(self:Self, _type:str, string:str, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, default_message:str = None, i:int = 0) -> None:
|
def print(self:Self,
|
||||||
|
_type:str,
|
||||||
|
string:str,
|
||||||
|
inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None,
|
||||||
|
default_message:str = None,
|
||||||
|
i:int = 0
|
||||||
|
) -> None:
|
||||||
|
|
||||||
date:datetime = datetime.now()
|
date:datetime = datetime.now()
|
||||||
own:dict[str, Any|None] = {
|
own:dict[str, Any|None] = {
|
||||||
@ -54,6 +75,9 @@ class OpoTests:
|
|||||||
|
|
||||||
own["yyyy"] = ("0000" + str(own["year"]))[-4:]
|
own["yyyy"] = ("0000" + str(own["year"]))[-4:]
|
||||||
|
|
||||||
|
if "end" in own:
|
||||||
|
own["message"] += own["end"]
|
||||||
|
|
||||||
print(Utils.string_variables(self.__print_format, own))
|
print(Utils.string_variables(self.__print_format, own))
|
||||||
|
|
||||||
def exception(self,
|
def exception(self,
|
||||||
@ -84,4 +108,27 @@ class OpoTests:
|
|||||||
|
|
||||||
data["end"] = Utils.string_variables(self.__exception_format, data)
|
data["end"] = Utils.string_variables(self.__exception_format, data)
|
||||||
|
|
||||||
message and self.print("exception", message, data, i + 1)
|
message and self.print("exception", message, data, None, i + 1)
|
||||||
|
|
||||||
|
def load_json_data(self:Self,
|
||||||
|
inputs:Optional[str|dict[str, Any|None]|list[Any|None]|tuple[Any|None]],
|
||||||
|
only_dictionaries:bool = True
|
||||||
|
) -> list[dict[str, Any|None]|list[Any|None]|tuple[Any|None]]:
|
||||||
|
|
||||||
|
json_items:list[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = []
|
||||||
|
|
||||||
|
if Check.is_dictionary(inputs):
|
||||||
|
json_items += [inputs]
|
||||||
|
elif Check.is_array(inputs):
|
||||||
|
if only_dictionaries:
|
||||||
|
for item in inputs:
|
||||||
|
if Check.is_dictionary(item):
|
||||||
|
json_items += [item]
|
||||||
|
else:
|
||||||
|
json_items += self.load_json_data(item, only_dictionaries)
|
||||||
|
else:
|
||||||
|
json_items += [inputs]
|
||||||
|
elif Check.is_string(inputs):
|
||||||
|
json_items += self.load_json_data(Utils.json_decode(inputs) or self.files.load(inputs, True), only_dictionaries)
|
||||||
|
|
||||||
|
return json_items
|
||||||
17
Python/Controllers/TestController.py
Normal file
17
Python/Controllers/TestController.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from Abstracts.ControllersAbstract import ControllersAbstract
|
||||||
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
|
from Models.RequestModel import RequestModel
|
||||||
|
from typing import Any, Self
|
||||||
|
|
||||||
|
class TestController(ControllersAbstract):
|
||||||
|
|
||||||
|
def __init__(self:Self, ot:OpoTestsInterface) -> None:
|
||||||
|
super().__init__(ot, {
|
||||||
|
"ping": self.ping
|
||||||
|
})
|
||||||
|
|
||||||
|
def ping(self:Self, request:RequestModel) -> tuple[Any|None, dict[str, Any|None]]:
|
||||||
|
return ("pong", {"mime" : "text/plain"})
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from typing import Self
|
from typing import Self
|
||||||
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
@ -21,6 +22,9 @@ class FilesDriver:
|
|||||||
|
|
||||||
mimetypes.init()
|
mimetypes.init()
|
||||||
|
|
||||||
|
def start(self:Self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
def fix_path(self:Self, path:str) -> str:
|
def fix_path(self:Self, path:str) -> str:
|
||||||
return RE.SLASHES.sub(self.__slash, path)
|
return RE.SLASHES.sub(self.__slash, path)
|
||||||
|
|
||||||
@ -36,13 +40,13 @@ class FilesDriver:
|
|||||||
return absolute_path
|
return absolute_path
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def load(self:Self, path:str) -> bytes|None:
|
def load(self:Self, path:str, as_string:bool = False) -> bytes|str|None:
|
||||||
|
|
||||||
absolute:str = self.get_absolute_path(path)
|
absolute:str = self.get_absolute_path(path)
|
||||||
|
|
||||||
if absolute and is_file(absolute):
|
if absolute and is_file(absolute):
|
||||||
try:
|
try:
|
||||||
with open(absolute, "rb") as file:
|
with open(absolute, "r" if as_string else "rb") as file:
|
||||||
return file.read()
|
return file.read()
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
print(["files_load", exception])
|
print(["files_load", exception])
|
||||||
|
|||||||
@ -1,28 +1,40 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import Any, Self, Optional
|
from typing import Any, Self, Optional
|
||||||
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
|
from Models.RequestModel import RequestModel
|
||||||
from socket import socket as Socket
|
from socket import socket as Socket
|
||||||
from socket import AF_INET as ADDRESS_FAMILY_IPV4
|
from socket import AF_INET as ADDRESS_FAMILY_IPV4
|
||||||
from socket import SOCK_STREAM as SOCKET_STREAM
|
from socket import SOCK_STREAM as SOCKET_STREAM
|
||||||
from socket import SOL_SOCKET as SOCKET_LAYER
|
from socket import SOL_SOCKET as SOCKET_LAYER
|
||||||
from socket import SO_REUSEADDR as SOCKET_REUSE_ADDRESS
|
from socket import SO_REUSEADDR as SOCKET_REUSE_ADDRESS
|
||||||
from Utils.Patterns import RE
|
from Utils.Utils import Utils
|
||||||
|
from Utils.Check import Check
|
||||||
|
|
||||||
class HTTPSocketDriver:
|
class HTTPSocketDriver:
|
||||||
|
|
||||||
def __init__(self:Self, ot:OpoTestsInterface, inputs:Optional[dict[str, Any|None]|tuple[Any|None]|list] = None) -> None:
|
def __init__(self:Self, ot:OpoTestsInterface, inputs:Optional[dict[str, Any|None]|tuple[Any|None]|list] = None) -> None:
|
||||||
self.ot:OpoTestsInterface = ot
|
self.ot:OpoTestsInterface = ot
|
||||||
|
self.__inputs:dict[str, Any|None] = Utils.get_dictionary(inputs)
|
||||||
self.__socket:Socket|None = None
|
self.__socket:Socket|None = None
|
||||||
self.__address:str = self.ot.settings.get(("address", "http_address"), inputs, "localhost")
|
self.__address:str = "localhost"
|
||||||
self.__port:int = self.ot.settings.get(("port", "http_port"), inputs, 8080)
|
self.__port:int = 8080
|
||||||
self.__maximum_connections:int = self.ot.settings.get(("maximum_connections", "http_maximum_connections"), inputs, 5)
|
self.__maximum_connections:int = 5
|
||||||
self.__cache_size:int = self.ot.settings.get(("cache_size", "http_cache_size"), inputs, 1024)
|
self.__cache_size:int = 1024
|
||||||
self.__public_path:str = self.ot.settings.get(("public_path", "http_public_path"), inputs, "/Public")
|
self.__public_path:str = "/Public"
|
||||||
|
self.__index_files:list[str] = ["index.html", "index.htm"]
|
||||||
self.__working:bool = False
|
self.__working:bool = False
|
||||||
|
|
||||||
|
def update(self:Self) -> None:
|
||||||
|
self.__address = self.ot.settings.get(("address", "http_address"), self.__inputs, self.__address)
|
||||||
|
self.__port = self.ot.settings.get(("port", "http_port"), self.__inputs, self.__port)
|
||||||
|
self.__maximum_connections = self.ot.settings.get(("maximum_connections", "http_maximum_connections"), self.__inputs, self.__maximum_connections)
|
||||||
|
self.__cache_size = self.ot.settings.get(("cache_size", "http_cache_size"), self.__inputs, self.__cache_size)
|
||||||
|
self.__public_path = self.ot.settings.get(("public_path", "http_public_path"), self.__inputs, self.__public_path)
|
||||||
|
self.__index_files = self.ot.settings.get(("index_files", "http_index_files"), self.__inputs, self.__index_files)
|
||||||
|
|
||||||
def __listen(self:Self) -> None:
|
def __listen(self:Self) -> None:
|
||||||
while self.__working:
|
while self.__working:
|
||||||
try:
|
try:
|
||||||
@ -31,6 +43,8 @@ class HTTPSocketDriver:
|
|||||||
address:str
|
address:str
|
||||||
port:int
|
port:int
|
||||||
data:bytes = b""
|
data:bytes = b""
|
||||||
|
response:Any|None
|
||||||
|
parameters:dict[str, Any|None]
|
||||||
|
|
||||||
client, (address, port) = self.__socket.accept()
|
client, (address, port) = self.__socket.accept()
|
||||||
|
|
||||||
@ -42,21 +56,34 @@ class HTTPSocketDriver:
|
|||||||
if len(buffer) < self.__cache_size:
|
if len(buffer) < self.__cache_size:
|
||||||
break
|
break
|
||||||
|
|
||||||
file_data:bytes|None
|
response, parameters = self.ot.routes.go(RequestModel(data.decode("utf-8"), {
|
||||||
|
"address" : address,
|
||||||
|
"port" : port,
|
||||||
|
"client" : client,
|
||||||
|
"public_path" : self.__public_path,
|
||||||
|
"index_files" : ["", *self.__index_files]
|
||||||
|
}))
|
||||||
|
|
||||||
|
client.sendall(
|
||||||
|
str(Utils.string_variables((
|
||||||
|
"{http_protocol}/{http_version} {http_code} {http_message}\r\n" +
|
||||||
|
"Content-Type: {mime}"
|
||||||
|
), {
|
||||||
|
"http_protocol" : "HTTP",
|
||||||
|
"http_version" : "1.1",
|
||||||
|
"http_code" : 200,
|
||||||
|
"http_message" : "OK",
|
||||||
|
"mime" : "text/plain",
|
||||||
|
**parameters
|
||||||
|
})).encode("utf-8") +
|
||||||
|
b"\r\n\r\n" +
|
||||||
|
(
|
||||||
|
str(response).encode("utf-8") if Check.is_string(response) else
|
||||||
|
response if Check.is_bytes(response) else
|
||||||
|
Utils.json_encode(response).encode("utf-8") if Check.is_json_object(response) else
|
||||||
|
bytes(response))
|
||||||
|
)
|
||||||
|
|
||||||
for index in ("", "/index.html", "/index.htm"):
|
|
||||||
|
|
||||||
path:str = self.__public_path + RE.LINE.match(data.decode("utf-8")).group(1).split(" ")[1] + index
|
|
||||||
|
|
||||||
file_data = self.ot.files.load(path)
|
|
||||||
|
|
||||||
if file_data is not None:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not file_data:
|
|
||||||
client.sendall(b"HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\n404 Not Found")
|
|
||||||
else:
|
|
||||||
client.sendall(b"HTTP/1.1 200 OK\r\nContent-Type: " + self.ot.files.get_mime(path).encode("utf-8") + b"\r\n\r\n" + file_data)
|
|
||||||
client.close()
|
client.close()
|
||||||
|
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
@ -70,6 +97,8 @@ class HTTPSocketDriver:
|
|||||||
self.__working = True
|
self.__working = True
|
||||||
self.__socket = Socket(ADDRESS_FAMILY_IPV4, SOCKET_STREAM)
|
self.__socket = Socket(ADDRESS_FAMILY_IPV4, SOCKET_STREAM)
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
self.__socket.setsockopt(SOCKET_LAYER, SOCKET_REUSE_ADDRESS, 1)
|
self.__socket.setsockopt(SOCKET_LAYER, SOCKET_REUSE_ADDRESS, 1)
|
||||||
|
|||||||
17
Python/Interfaces/ControllersAbstractInterface.py
Normal file
17
Python/Interfaces/ControllersAbstractInterface.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Callable
|
||||||
|
|
||||||
|
class ControllersAbstractInterface:
|
||||||
|
|
||||||
|
def add(self:Self, key:str, action:Callable[[
|
||||||
|
dict[str, Any|None],
|
||||||
|
dict[str, Any|None]
|
||||||
|
], Any|None], overwrite:bool = False) -> None:pass
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
action:str,
|
||||||
|
variables:dict[str, Any|None],
|
||||||
|
inputs:dict[str, Any|None]
|
||||||
|
) -> Any|None:pass
|
||||||
16
Python/Interfaces/ControllersManagerInterface.py
Normal file
16
Python/Interfaces/ControllersManagerInterface.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Callable
|
||||||
|
from Interfaces.ControllersAbstractInterface import ControllersAbstractInterface
|
||||||
|
|
||||||
|
class ControllersManagerInterface:
|
||||||
|
|
||||||
|
def start(self:Self) -> None:pass
|
||||||
|
|
||||||
|
def add(self:Self, inputs:str|ControllersAbstractInterface|list|tuple, overwrite:bool = False) -> None:pass
|
||||||
|
|
||||||
|
def get(self:Self, key:str, action:str) -> Callable[[
|
||||||
|
dict[str, Any|None],
|
||||||
|
dict[str, Any|None]
|
||||||
|
], Any|None]|None:pass
|
||||||
@ -1,13 +1,16 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from typing import Self
|
from typing import Self
|
||||||
|
|
||||||
class FilesDriverInterface:
|
class FilesDriverInterface:
|
||||||
|
|
||||||
|
def start(self:Self) -> None:pass
|
||||||
|
|
||||||
def fix_path(self:Self, path:str) -> str:pass
|
def fix_path(self:Self, path:str) -> str:pass
|
||||||
|
|
||||||
def get_absolute_path(self:Self, path:str) -> str|None:pass
|
def get_absolute_path(self:Self, path:str) -> str|None:pass
|
||||||
|
|
||||||
def load(self:Self, path:str) -> bytes|None:pass
|
def load(self:Self, path:str, as_string:bool = False) -> bytes|str|None:pass
|
||||||
|
|
||||||
def get_mime(self:Self, path:str) -> str|None:pass
|
def get_mime(self:Self, path:str) -> str|None:pass
|
||||||
27
Python/Interfaces/FormatModeInterface.py
Normal file
27
Python/Interfaces/FormatModeInterface.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from Interfaces.FormatModuleInterface import FormatModuleInterface
|
||||||
|
from typing import Any, Self, Optional
|
||||||
|
|
||||||
|
class FormatModeInterface:
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
format:FormatModuleInterface,
|
||||||
|
options:Optional[dict[str, Any|None]] = None
|
||||||
|
) -> None:pass
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
i:int,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:pass
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> int:pass
|
||||||
59
Python/Interfaces/FormatModuleInterface.py
Normal file
59
Python/Interfaces/FormatModuleInterface.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
|
from typing import Self, Any
|
||||||
|
|
||||||
|
class FormatModuleInterface:
|
||||||
|
|
||||||
|
def __init__(self:Self, op:OpoTestsInterface) -> None:
|
||||||
|
self.op:OpoTestsInterface = op
|
||||||
|
|
||||||
|
def start(self:Self) -> None:pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_fragments_level(string:str, fragments:list[str]) -> str:pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def build_fragments(cls:type[Self], string:str, fragments:list[str] = []) -> str:pass
|
||||||
|
|
||||||
|
def execute(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def prepare_result(string:str, option:str, shared:dict[str, Any|None]) -> int:pass
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
options:str|list[str],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = [],
|
||||||
|
check_full:bool = True
|
||||||
|
) -> tuple[bool, int]:pass
|
||||||
|
|
||||||
|
def get_check_length(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
options:str|list[str],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = [],
|
||||||
|
check_full:bool = True
|
||||||
|
) -> int:pass
|
||||||
|
|
||||||
|
def check_select(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
options:tuple[tuple[int, int], str, list[str]],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str|None:pass
|
||||||
|
|
||||||
|
def get_list(self:Self, i:int, items:list[str]) -> list[str]:pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_range(string:str, inputs:str|list[str]) -> int:pass
|
||||||
@ -1,4 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
class HTTPSocketDriverInterface:
|
class HTTPSocketDriverInterface:
|
||||||
pass
|
|
||||||
|
def start(self:Self) -> None:pass
|
||||||
@ -1,7 +1,10 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional, Self
|
||||||
|
|
||||||
class I18NManagerInterface:
|
class I18NManagerInterface:
|
||||||
|
|
||||||
|
def start(self:Self) -> None:pass
|
||||||
|
|
||||||
def get(self, texts:str|list|tuple, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, _default:Optional[Any] = None) -> str|None:pass
|
def get(self, texts:str|list|tuple, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, _default:Optional[Any] = None) -> str|None:pass
|
||||||
@ -1,10 +1,15 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from typing import Self, Any, Optional
|
from typing import Self, Any, Optional
|
||||||
from Interfaces.SettingsManagerInterface import SettingsManagerInterface
|
from Interfaces.SettingsManagerInterface import SettingsManagerInterface
|
||||||
from Interfaces.I18NManagerInterface import I18NManagerInterface
|
from Interfaces.I18NManagerInterface import I18NManagerInterface
|
||||||
from Interfaces.HTTPSocketDriverInterface import HTTPSocketDriverInterface
|
from Interfaces.HTTPSocketDriverInterface import HTTPSocketDriverInterface
|
||||||
from Interfaces.FilesDriverInterface import FilesDriverInterface
|
from Interfaces.FilesDriverInterface import FilesDriverInterface
|
||||||
|
from Interfaces.QuestionsManagerInterface import QuestionsManagerInterface
|
||||||
|
from Interfaces.UsersManagerInterface import UsersManagerInterface
|
||||||
|
from Interfaces.RoutesManagerInterface import RoutesManagerInterface
|
||||||
|
from Interfaces.ControllersManagerInterface import ControllersManagerInterface
|
||||||
|
|
||||||
class OpoTestsInterface:
|
class OpoTestsInterface:
|
||||||
|
|
||||||
@ -13,6 +18,10 @@ class OpoTestsInterface:
|
|||||||
self.i18n:I18NManagerInterface = None
|
self.i18n:I18NManagerInterface = None
|
||||||
self.http_server:HTTPSocketDriverInterface = None
|
self.http_server:HTTPSocketDriverInterface = None
|
||||||
self.files:FilesDriverInterface = None
|
self.files:FilesDriverInterface = None
|
||||||
|
self.users:UsersManagerInterface = None
|
||||||
|
self.questions:QuestionsManagerInterface = None
|
||||||
|
self.routes:RoutesManagerInterface = None
|
||||||
|
self.controllers:ControllersManagerInterface = None
|
||||||
|
|
||||||
def print(self:Self, _type:str, string:str, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, i:int = 0) -> None:pass
|
def print(self:Self, _type:str, string:str, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, i:int = 0) -> None:pass
|
||||||
|
|
||||||
@ -21,4 +30,9 @@ class OpoTestsInterface:
|
|||||||
message:Optional[str|list|tuple] = None,
|
message:Optional[str|list|tuple] = None,
|
||||||
variables:Optional[dict[str, Any]|list|tuple] = None,
|
variables:Optional[dict[str, Any]|list|tuple] = None,
|
||||||
i:Optional[int] = 1
|
i:Optional[int] = 1
|
||||||
) -> None:pass
|
) -> None:pass
|
||||||
|
|
||||||
|
def load_json_data(self:Self,
|
||||||
|
inputs:Optional[str|dict[str, Any|None]|list[Any|None]|tuple[Any|None]],
|
||||||
|
only_dictionaries:bool = True
|
||||||
|
) -> list[dict[str, Any|None]|list[Any|None]|tuple[Any|None]]:pass
|
||||||
19
Python/Interfaces/QuestionsManagerInterface.py
Normal file
19
Python/Interfaces/QuestionsManagerInterface.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Optional
|
||||||
|
|
||||||
|
class QuestionsManagerInterface:
|
||||||
|
|
||||||
|
def start(self:Self) -> None:pass
|
||||||
|
|
||||||
|
def update(self:Self) -> None:pass
|
||||||
|
|
||||||
|
def empty(self:Self) -> None:pass
|
||||||
|
|
||||||
|
def add(self:Self,
|
||||||
|
inputs:dict[str, Any|None]|list[Any|None]|tuple[Any|None]|str,
|
||||||
|
overwrite:bool = False
|
||||||
|
) -> None:pass
|
||||||
|
|
||||||
|
def get_value(self:Self, key:str, i:Optional[int] = None) -> Any|None:pass
|
||||||
13
Python/Interfaces/RoutesManagerInterface.py
Normal file
13
Python/Interfaces/RoutesManagerInterface.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self
|
||||||
|
from Models.RouteModel import RouteModel
|
||||||
|
|
||||||
|
class RoutesManagerInterface:
|
||||||
|
|
||||||
|
def start(self:Self) -> None:pass
|
||||||
|
|
||||||
|
def add(self:Self, inputs:str|RouteModel|list|tuple, overwrite:bool = False) -> None:pass
|
||||||
|
|
||||||
|
def go(self:Self, method:str, request:str, inputs:dict) -> None:pass
|
||||||
@ -1,7 +1,10 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional, Self
|
||||||
|
|
||||||
class SettingsManagerInterface:
|
class SettingsManagerInterface:
|
||||||
|
|
||||||
|
def start(self:Self) -> None:pass
|
||||||
|
|
||||||
def get(self, keys:str|list|tuple, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, _default:Optional[Any] = None) -> Any|None:pass
|
def get(self, keys:str|list|tuple, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, _default:Optional[Any] = None) -> Any|None:pass
|
||||||
16
Python/Interfaces/UsersManagerInterface.py
Normal file
16
Python/Interfaces/UsersManagerInterface.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
|
class UsersManagerInterface:
|
||||||
|
|
||||||
|
def start(self:Self) -> None:pass
|
||||||
|
|
||||||
|
def update(self:Self) -> None:pass
|
||||||
|
|
||||||
|
def empty(self:Self) -> None:pass
|
||||||
|
|
||||||
|
def add(self:Self, inputs:dict[str, str]|list|tuple|str, overwrite:bool = False) -> None:pass
|
||||||
|
|
||||||
|
def validate(self:Self, nick:str, password:str) -> bool:pass
|
||||||
36
Python/Managers/ControllersManager.py
Normal file
36
Python/Managers/ControllersManager.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any
|
||||||
|
from Interfaces.ControllersAbstractInterface import ControllersAbstractInterface
|
||||||
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
|
from Models.RequestModel import RequestModel
|
||||||
|
|
||||||
|
class ControllersManager:
|
||||||
|
|
||||||
|
def __init__(self:Self, ot:OpoTestsInterface) -> None:
|
||||||
|
self.ot:OpoTestsInterface = ot
|
||||||
|
self.__controllers:dict[str, ControllersAbstractInterface] = {}
|
||||||
|
|
||||||
|
def start(self:Self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def add(self:Self, inputs:str|ControllersAbstractInterface|list|tuple, overwrite:bool = False) -> None:
|
||||||
|
|
||||||
|
item:dict[str, ControllersAbstractInterface]
|
||||||
|
|
||||||
|
for item in self.ot.load_json_data(inputs, False) or (inputs,):
|
||||||
|
|
||||||
|
key:str
|
||||||
|
controller:ControllersAbstractInterface
|
||||||
|
|
||||||
|
for key, controller in item.items():
|
||||||
|
if overwrite or key not in self.__controllers:
|
||||||
|
self.__controllers[key] = controller
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
key:str,
|
||||||
|
action:str,
|
||||||
|
request:RequestModel
|
||||||
|
) -> tuple[Any|None, dict[str, Any|None]]|None:
|
||||||
|
return self.__controllers[key].get(action, request) if key in self.__controllers else None
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
from typing import Any, Optional, Self
|
from typing import Any, Optional, Self
|
||||||
@ -14,6 +15,37 @@ class I18NManager:
|
|||||||
self.__sentences:dict[str, dict[str, str|list[str]|tuple[str]]] = {}
|
self.__sentences:dict[str, dict[str, str|list[str]|tuple[str]]] = {}
|
||||||
self.__default_language:str = "espanol"
|
self.__default_language:str = "espanol"
|
||||||
self.__language_selected:str = "espanol"
|
self.__language_selected:str = "espanol"
|
||||||
|
|
||||||
|
def start(self:Self) -> None:
|
||||||
|
|
||||||
|
key:str
|
||||||
|
|
||||||
|
self.__default_language = self.ot.settings.get(("default_language", "i18n_default_language"), None, self.__default_language)
|
||||||
|
self.__language_selected = self.ot.settings.get(("language_selected", "i18n_language_selected"), None, self.__language_selected)
|
||||||
|
|
||||||
|
for key in ("default_i18n_files", "default_i18n", "i18n_files", "i18n"):
|
||||||
|
self.add(self.ot.settings.get(key), True)
|
||||||
|
|
||||||
|
def add(self:Self, inputs:dict[str, Any|None]|str|list|tuple, overwrite:bool = False) -> None:
|
||||||
|
|
||||||
|
set:dict[str, Any|None]
|
||||||
|
|
||||||
|
for set in self.ot.load_json_data(inputs):
|
||||||
|
|
||||||
|
language:str
|
||||||
|
sentences:dict[str, str|list|tuple|None]
|
||||||
|
|
||||||
|
for language, sentences in set.items():
|
||||||
|
if Check.is_dictionary(sentences):
|
||||||
|
|
||||||
|
key:str
|
||||||
|
text:str|list[str]|tuple[str]|None
|
||||||
|
|
||||||
|
if language not in self.__sentences:
|
||||||
|
self.__sentences[language] = {}
|
||||||
|
for key, text in sentences.items():
|
||||||
|
if overwrite or key not in self.__sentences[language]:
|
||||||
|
self.__sentences[language][key] = text
|
||||||
|
|
||||||
def get(self:Self, texts:str|list|tuple, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, _default:Optional[Any] = None) -> str|None:
|
def get(self:Self, texts:str|list|tuple, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, _default:Optional[Any] = None) -> str|None:
|
||||||
|
|
||||||
|
|||||||
94
Python/Managers/QuestionsManager.py
Normal file
94
Python/Managers/QuestionsManager.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
|
from typing import Self, Any, Optional
|
||||||
|
from Models.QuestionModel import QuestionModel
|
||||||
|
from Models.SetModel import SetModel
|
||||||
|
|
||||||
|
class QuestionsManager:
|
||||||
|
|
||||||
|
def __init__(self:Self, ot:OpoTestsInterface) -> None:
|
||||||
|
self.ot:OpoTestsInterface = ot
|
||||||
|
self.__sets:list[SetModel] = []
|
||||||
|
self.__groups:list[str] = []
|
||||||
|
self.__groups_variables:list[dict[str, Any]] = []
|
||||||
|
self.__questions:list[QuestionModel] = []
|
||||||
|
self.__variables:dict[str, Any] = {}
|
||||||
|
|
||||||
|
def start(self:Self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update(self:Self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def empty(self:Self) -> None:
|
||||||
|
self.__sets = []
|
||||||
|
self.__groups = []
|
||||||
|
self.__groups_variables:list[dict[str, Any]] = []
|
||||||
|
self.__questions = []
|
||||||
|
|
||||||
|
def add(self:Self,
|
||||||
|
inputs:dict[str, Any|None]|list[Any|None]|tuple[Any|None]|str,
|
||||||
|
overwrite:bool = False
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
set_data:dict[str, Any|None]
|
||||||
|
|
||||||
|
for set_data in self.ot.load_json_data(inputs):
|
||||||
|
|
||||||
|
set:SetModel = SetModel(set_data, len(self.__sets))
|
||||||
|
group_done:bool = False
|
||||||
|
key:str
|
||||||
|
question_data:dict[str, Any|None]
|
||||||
|
group_variables:dict[str, Any|None]|None = set_data.get("group_variables")
|
||||||
|
variables:dict[str, Any|None]|None = set_data.get("variables")
|
||||||
|
|
||||||
|
variables and self.__variables.update(variables)
|
||||||
|
|
||||||
|
for set.group_i, key in enumerate(self.__groups):
|
||||||
|
if key == set.group:
|
||||||
|
group_done = True
|
||||||
|
group_variables and self.__groups_variables[set.group_i].update(group_variables)
|
||||||
|
break
|
||||||
|
|
||||||
|
if not group_done:
|
||||||
|
set.group_i += 1
|
||||||
|
self.__groups += [set.group]
|
||||||
|
if group_variables:
|
||||||
|
self.__groups_variables += [group_variables]
|
||||||
|
|
||||||
|
for question_data in set_data.get("queries", []):
|
||||||
|
|
||||||
|
variables:dict[str, Any|None]|None = question_data.get("variables")
|
||||||
|
question:QuestionModel = QuestionModel(question_data, set)
|
||||||
|
allowed:bool = True
|
||||||
|
|
||||||
|
variables and self.__variables.update(variables)
|
||||||
|
|
||||||
|
for i, existing_question in enumerate(self.__questions):
|
||||||
|
if (
|
||||||
|
existing_question.set == question.set and
|
||||||
|
existing_question.group == question.group and
|
||||||
|
len(existing_question.questions) == len(question.questions) and
|
||||||
|
not any(question_string != question.questions[j] for j, question_string in enumerate(existing_question.questions))
|
||||||
|
):
|
||||||
|
if overwrite:
|
||||||
|
self.__questions[i] = question
|
||||||
|
allowed = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if allowed:
|
||||||
|
self.__questions += [question]
|
||||||
|
|
||||||
|
def get_value(self:Self, key:str, i:Optional[int] = None) -> Any|None:
|
||||||
|
|
||||||
|
set:dict[str, Any]
|
||||||
|
|
||||||
|
for set in ([] if i is None else [
|
||||||
|
self.__questions[i].own_variables,
|
||||||
|
self.__groups_variables[self.__questions[i].group]
|
||||||
|
]) + [self.__variables]:
|
||||||
|
if key in set:
|
||||||
|
return set[key]
|
||||||
|
return None
|
||||||
97
Python/Managers/RoutesManager.py
Normal file
97
Python/Managers/RoutesManager.py
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any
|
||||||
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
|
from Models.RouteModel import RouteModel
|
||||||
|
from re import Match as REMatch
|
||||||
|
from Models.RequestModel import RequestModel
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
|
||||||
|
class RoutesManager:
|
||||||
|
|
||||||
|
def __init__(self:Self, ot:OpoTestsInterface) -> None:
|
||||||
|
self.ot:OpoTestsInterface = ot
|
||||||
|
self.__routes:tuple[RouteModel] = tuple()
|
||||||
|
|
||||||
|
def start(self:Self) -> None:
|
||||||
|
|
||||||
|
key:str
|
||||||
|
|
||||||
|
for key in ("default_routes_files", "default_routes", "routes_files", "routes"):
|
||||||
|
self.add(self.ot.settings.get(key, []), True)
|
||||||
|
|
||||||
|
def add(self:Self, inputs:str|RouteModel|list|tuple, overwrite:bool = False) -> None:
|
||||||
|
|
||||||
|
item:str|RouteModel|list|tuple
|
||||||
|
|
||||||
|
for item in self.ot.load_json_data(inputs, False) or (inputs,):
|
||||||
|
if Check.is_string(item):
|
||||||
|
|
||||||
|
route:RouteModel = RouteModel(item)
|
||||||
|
|
||||||
|
if route.done:
|
||||||
|
self.__routes += (route,)
|
||||||
|
else:
|
||||||
|
self.add(item, overwrite)
|
||||||
|
|
||||||
|
elif isinstance(item, RouteModel):
|
||||||
|
if item.done:
|
||||||
|
self.__routes += (item,)
|
||||||
|
elif Check.is_array(item):
|
||||||
|
if len(item) == 6 and all(subitem is None or Check.is_string(subitem) for subitem in item):
|
||||||
|
|
||||||
|
route:RouteModel = RouteModel(item)
|
||||||
|
|
||||||
|
if route.done:
|
||||||
|
self.__routes += (route,)
|
||||||
|
continue
|
||||||
|
|
||||||
|
for subitem in item:
|
||||||
|
self.add(subitem, overwrite)
|
||||||
|
|
||||||
|
def go(self:Self, request:RequestModel) -> tuple[Any|None, int]:
|
||||||
|
|
||||||
|
route:RouteModel
|
||||||
|
|
||||||
|
for route in self.__routes:
|
||||||
|
if route.method == request.method:
|
||||||
|
|
||||||
|
matches:REMatch = route.request.match(request.request)
|
||||||
|
|
||||||
|
if not matches:
|
||||||
|
continue
|
||||||
|
|
||||||
|
request.variables_request = {
|
||||||
|
route.variables[i] : value for i, value in enumerate(matches.groups()[1:])
|
||||||
|
}
|
||||||
|
|
||||||
|
if route.path:
|
||||||
|
for index in request.index_files:
|
||||||
|
|
||||||
|
path:str = request.public_path + '/' + request.request + ('/' + index if index else '')
|
||||||
|
data:bytes|None = self.ot.files.load(path)
|
||||||
|
|
||||||
|
if data is not None:
|
||||||
|
return (data, {"mime" : self.ot.files.get_mime(path)})
|
||||||
|
|
||||||
|
elif route.controller:
|
||||||
|
|
||||||
|
data:tuple[Any|None, dict[str, Any|None]]|None = self.ot.controllers.get(
|
||||||
|
route.controller,
|
||||||
|
route.action,
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
|
if data is not None:
|
||||||
|
return data
|
||||||
|
|
||||||
|
return (Utils.json_encode({
|
||||||
|
"ok" : False,
|
||||||
|
"code" : 404,
|
||||||
|
"message" : "Not found"
|
||||||
|
}), {
|
||||||
|
"http_code" : 404,
|
||||||
|
"mime" : "application/json"
|
||||||
|
})
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
from typing import Any, Optional, Self
|
from typing import Any, Optional, Self
|
||||||
@ -6,13 +7,54 @@ from Utils.Utils import Utils
|
|||||||
|
|
||||||
class SettingsManager:
|
class SettingsManager:
|
||||||
|
|
||||||
DEFAULT_SETTINGS:dict[str, Any|None] = {}
|
DEFAULT_SETTINGS:dict[str, Any|None] = {
|
||||||
|
"default_settings_files" : ["/JSON/OpoTests.settings.json"],
|
||||||
|
"default_secrets_files" : ["/JSON/OpoTests.secrets.json"]
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self:Self, ot:OpoTestsInterface, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None) -> None:
|
def __init__(self:Self,
|
||||||
|
ot:OpoTestsInterface,
|
||||||
|
inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None
|
||||||
|
) -> None:
|
||||||
self.ot:OpoTestsInterface = ot
|
self.ot:OpoTestsInterface = ot
|
||||||
self.__customs:dict[str, Any|None] = Utils.get_dictionary(inputs)
|
self.__customs:dict[str, Any|None] = Utils.get_dictionary(inputs)
|
||||||
self.__settings:dict[str, Any|None] = {}
|
self.__settings:dict[str, Any|None] = {}
|
||||||
self.__secrets:dict[str, Any|None] = {}
|
self.__secrets:dict[str, Any|None] = {}
|
||||||
|
|
||||||
|
def start(self:Self) -> None:
|
||||||
|
|
||||||
|
key:str
|
||||||
|
|
||||||
|
for key in ("default_settings_files", "default_settings", "settings_files", "settings"):
|
||||||
|
self.add(self.get(key), True)
|
||||||
|
for key in ("default_secrets_files", "default_secrets", "secrets_files", "secrets"):
|
||||||
|
self.add_secrets(self.get(key), True)
|
||||||
|
|
||||||
|
def add(self:Self, inputs:dict[str, Any|None]|str|list|tuple, overwrite:bool = False) -> None:
|
||||||
|
|
||||||
|
set:dict[str, Any|None]
|
||||||
|
|
||||||
|
for set in self.ot.load_json_data(inputs):
|
||||||
|
|
||||||
|
key:str
|
||||||
|
value:Any|None
|
||||||
|
|
||||||
|
for key, value in set.items():
|
||||||
|
if overwrite or key not in self.__settings:
|
||||||
|
self.__settings[key] = value
|
||||||
|
|
||||||
|
def add_secrets(self:Self, inputs:dict[str, Any|None]|str|list|tuple, overwrite:bool = False) -> None:
|
||||||
|
|
||||||
|
set:dict[str, Any|None]
|
||||||
|
|
||||||
|
for set in self.ot.load_json_data(inputs):
|
||||||
|
|
||||||
|
key:str
|
||||||
|
value:Any|None
|
||||||
|
|
||||||
|
for key, value in set.items():
|
||||||
|
if overwrite or key not in self.__secrets:
|
||||||
|
self.__secrets[key] = value
|
||||||
|
|
||||||
def get(self:Self, keys:str|list|tuple, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, _default:Optional[Any] = None) -> Any|None:
|
def get(self:Self, keys:str|list|tuple, inputs:Optional[dict[str, Any|None]|list[Any|None]|tuple[Any|None]] = None, _default:Optional[Any] = None) -> Any|None:
|
||||||
return Utils.get_values(keys, (inputs, self.__customs, self.__secrets, self.__settings, self.DEFAULT_SETTINGS), _default)
|
return Utils.get_values(keys, (inputs, self.__customs, self.__secrets, self.__settings, self.DEFAULT_SETTINGS), _default)
|
||||||
55
Python/Managers/UsersManager.py
Normal file
55
Python/Managers/UsersManager.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
|
from typing import Self
|
||||||
|
from Models.UserModel import UserModel
|
||||||
|
|
||||||
|
class UsersManager:
|
||||||
|
|
||||||
|
def __init__(self:Self, op:OpoTestsInterface) -> None:
|
||||||
|
self.op:OpoTestsInterface = op
|
||||||
|
self.__users:list[UserModel] = []
|
||||||
|
|
||||||
|
def start(self:Self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update(self:Self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def empty(self:Self) -> None:
|
||||||
|
self.__users = []
|
||||||
|
|
||||||
|
def add(self:Self, inputs:dict[str, str]|list|tuple|str, overwrite:bool = False) -> None:
|
||||||
|
|
||||||
|
users:dict[str, str]
|
||||||
|
|
||||||
|
for users in self.op.load_json_data(inputs):
|
||||||
|
|
||||||
|
nick:str
|
||||||
|
password:str
|
||||||
|
|
||||||
|
for nick, password in users.items():
|
||||||
|
|
||||||
|
i:int
|
||||||
|
user:UserModel
|
||||||
|
allowed:bool = True
|
||||||
|
|
||||||
|
for i, user in enumerate(self.__users):
|
||||||
|
if user.name == nick:
|
||||||
|
if overwrite:
|
||||||
|
self.__users[i] = UserModel(nick, password)
|
||||||
|
allowed = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if allowed:
|
||||||
|
self.__users += [UserModel(nick, password)]
|
||||||
|
|
||||||
|
def validate(self:Self, nick:str, password:str) -> bool:
|
||||||
|
|
||||||
|
user:UserModel
|
||||||
|
|
||||||
|
for user in self.__users:
|
||||||
|
if user.name == nick and user.password == password:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
20
Python/Models/QuestionModel.py
Normal file
20
Python/Models/QuestionModel.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Models.SetModel import SetModel
|
||||||
|
|
||||||
|
class QuestionModel:
|
||||||
|
|
||||||
|
def __init__(self:Self, data:dict[str, str|list[str]|bool|None], set:SetModel) -> None:
|
||||||
|
|
||||||
|
questions:str|list[str] = data.get("questions", [])
|
||||||
|
|
||||||
|
self.set:int = set.i
|
||||||
|
self.group:int = set.group_i
|
||||||
|
self.questions:list[str] = questions if Check.is_array(questions) else [questions]
|
||||||
|
self.rights:list[str] = data.get("rights")
|
||||||
|
self.wrongs:list[str] = data.get("wrongs", [])
|
||||||
|
self.own_variables:dict[str, Any] = data.get("own_variables", {})
|
||||||
|
self.brothers_are_wrongs:bool = data.get("brothers_are_wrongs", True)
|
||||||
78
Python/Models/RequestModel.py
Normal file
78
Python/Models/RequestModel.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Any, Self
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
from re import Match as REMatch
|
||||||
|
from socket import socket as Socket
|
||||||
|
|
||||||
|
class RequestModel:
|
||||||
|
|
||||||
|
def __init__(self:Self, data:str, inputs:dict[str, Any|None]) -> None:
|
||||||
|
|
||||||
|
header:list[str]
|
||||||
|
line:str
|
||||||
|
|
||||||
|
self.address:str = inputs.get("address")
|
||||||
|
self.port:int = inputs.get("port")
|
||||||
|
self.client:Socket = inputs.get("client")
|
||||||
|
self.public_path:str = inputs.get("public_path")
|
||||||
|
self.index_files:list[str] = inputs.get("index_files")
|
||||||
|
self.method:str
|
||||||
|
self.request:str
|
||||||
|
self.protocol:str
|
||||||
|
self.protocol_version:str
|
||||||
|
self.variables_get:dict[str, str] = {}
|
||||||
|
self.variables_post:dict[str, str] = {}
|
||||||
|
self.variables_request:dict[str, str] = {}
|
||||||
|
self.headers:dict[str, str] = {}
|
||||||
|
self.body:str|None
|
||||||
|
|
||||||
|
header, self.body = (lambda header, body:(
|
||||||
|
RE.NEW_LINE.split(str(header).strip()), body
|
||||||
|
))(*RE.HTTP_BLOCKS.match(data).groups())
|
||||||
|
|
||||||
|
(
|
||||||
|
self.method,
|
||||||
|
self.request,
|
||||||
|
self.variables_get,
|
||||||
|
self.protocol,
|
||||||
|
self.protocol_version
|
||||||
|
) = (lambda method, request, variables, protocol, protocol_version:(
|
||||||
|
str(method).lower(),
|
||||||
|
request,
|
||||||
|
self.parse_variables(variables),
|
||||||
|
protocol,
|
||||||
|
protocol_version
|
||||||
|
))(*RE.HTTP_REQUEST.match(header[0]).groups())
|
||||||
|
|
||||||
|
for line in header[1:]:
|
||||||
|
|
||||||
|
key:str
|
||||||
|
value:str
|
||||||
|
|
||||||
|
key, value = RE.HEADER_LINE.match(line).groups()
|
||||||
|
|
||||||
|
self.headers[key.strip().lower()] = value.strip()
|
||||||
|
|
||||||
|
self.variables_post = self.parse_variables(self.body or "")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_variables_set(data:str) -> dict[str, str]:
|
||||||
|
|
||||||
|
json:dict[str, str]|list[Any|None]|tuple[Any|None]|None = Utils.json_decode(data)
|
||||||
|
|
||||||
|
if Check.is_dictionary(json):
|
||||||
|
return json
|
||||||
|
return {key : value for key, value in RE.URI_VARIABLES.findall(data) or []}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse_variables(cls:type[Self], data:str|None) -> dict[str, str]:
|
||||||
|
return cls.parse_variables_set(
|
||||||
|
Utils.base64_decode(data) or data
|
||||||
|
) if data else {}
|
||||||
|
|
||||||
|
def set_request_variables(self:Self, matches:REMatch, keys:tuple[str]) -> None:
|
||||||
|
self.variables_request = {keys[i] : value for i, value in enumerate(matches.groups()[1:])}
|
||||||
61
Python/Models/RouteModel.py
Normal file
61
Python/Models/RouteModel.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
from re import Match as REMatch
|
||||||
|
from re import Pattern as REPattern
|
||||||
|
from re import compile as re_compile
|
||||||
|
|
||||||
|
class RouteModel:
|
||||||
|
|
||||||
|
def __init__(self:Self, inputs:str|list|tuple) -> None:
|
||||||
|
|
||||||
|
self.method:str
|
||||||
|
self.request:REPattern
|
||||||
|
self.controller:str
|
||||||
|
self.action:str
|
||||||
|
self.path:str|None
|
||||||
|
self.variables:tuple[str] = tuple()
|
||||||
|
self.permissions:list[str] = []
|
||||||
|
self.done:bool = False
|
||||||
|
|
||||||
|
if Check.is_string(inputs):
|
||||||
|
inputs = RE.ROUTE_ITEM.match(inputs).groups()
|
||||||
|
|
||||||
|
if Check.is_array(inputs):
|
||||||
|
|
||||||
|
self.done = True
|
||||||
|
(
|
||||||
|
self.method, self.request, self.action, self.controller, self.path, self.permissions
|
||||||
|
) = (lambda method, request, controller, action, path, permissions:(
|
||||||
|
method.lower(),
|
||||||
|
re_compile(r'^' + RE.ROUTE_RE_FORMAT.sub(
|
||||||
|
self.format_request_item,
|
||||||
|
RE.STRING_VARIABLES.sub(self.__add_variable, request)
|
||||||
|
) + (r'' if path else ('' if request[-1] == '/' else r'\/') + r'?$')),
|
||||||
|
controller,
|
||||||
|
action,
|
||||||
|
path,
|
||||||
|
(
|
||||||
|
[] if not permissions else
|
||||||
|
str(permissions).split(",") if Check.is_string(permissions) else
|
||||||
|
list(permissions) if Check.is_array(permissions) else
|
||||||
|
[])
|
||||||
|
))(*inputs)
|
||||||
|
|
||||||
|
def __add_variable(self:Self, key:str) -> str:
|
||||||
|
|
||||||
|
self.variables += (key,)
|
||||||
|
|
||||||
|
return r'([^\/]+)'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def format_request_item(matches:REMatch) -> str:
|
||||||
|
|
||||||
|
character:str = matches.group(2)
|
||||||
|
|
||||||
|
return '\\' + character if character else matches.group(1)
|
||||||
|
|
||||||
16
Python/Models/SetModel.py
Normal file
16
Python/Models/SetModel.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
|
||||||
|
class SetModel:
|
||||||
|
|
||||||
|
def __init__(self:Self, data:dict[str, Any|None], i:int) -> None:
|
||||||
|
self.origin:str = data.get("origin", "")
|
||||||
|
self.title:str = data.get("title", "")
|
||||||
|
self.group:None = data.get("group") or Utils.to_snake(self.title)
|
||||||
|
self.i:int = i
|
||||||
|
self.group_i:int
|
||||||
|
self.sources:list[str] = data.get("sources", [])
|
||||||
|
self.variables:dict[str, Any] = data.get("own_variables", {})
|
||||||
21
Python/Models/UserModel.py
Normal file
21
Python/Models/UserModel.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self
|
||||||
|
from Utils.Check import Check
|
||||||
|
|
||||||
|
class UserModel:
|
||||||
|
|
||||||
|
def __init__(self:Self, *arguments:list[dict[str, str]|str]) -> None:
|
||||||
|
|
||||||
|
self.name:str
|
||||||
|
self.password:str
|
||||||
|
|
||||||
|
if Check.is_dictionary(arguments[0]):
|
||||||
|
|
||||||
|
data:dict[str, str] = arguments[0]
|
||||||
|
|
||||||
|
self.name, self.password = data.get("name", ""), data.get("password", "")
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.name, self.password = arguments
|
||||||
46
Python/Modules/Format/CapitalizeFormat.py
Normal file
46
Python/Modules/Format/CapitalizeFormat.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Optional
|
||||||
|
from Interfaces.FormatModuleInterface import FormatModuleInterface
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
|
||||||
|
class CapitalizeFormat:
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
format:FormatModuleInterface,
|
||||||
|
options:Optional[dict[str, Any|None]] = None
|
||||||
|
) -> None:
|
||||||
|
self.format:FormatModuleInterface = format
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
i:int,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:
|
||||||
|
return RE.CAPITAL_CASE.sub(lambda matches:(
|
||||||
|
matches.group(1).upper()
|
||||||
|
), self.format.execute(i, (
|
||||||
|
inputs if Check.is_string(inputs) else
|
||||||
|
inputs[0] if Check.is_string(inputs[0]) else
|
||||||
|
""), shared, fragments))
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> int:
|
||||||
|
|
||||||
|
substring:str = self.format.set_fragments_level((
|
||||||
|
inputs if Check.is_string(inputs) else
|
||||||
|
inputs[0] if Check.is_string(inputs[0]) else
|
||||||
|
""), fragments)
|
||||||
|
has_variables:bool = RE.FRAGMENT_VARIABLES.search(substring) is not None
|
||||||
|
|
||||||
|
return (
|
||||||
|
self.format.get_check_length(i, string, substring, shared, fragments, False) if has_variables else
|
||||||
|
self.format.prepare_result(string, substring, shared))
|
||||||
76
Python/Modules/Format/MixFormat.py
Normal file
76
Python/Modules/Format/MixFormat.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Optional
|
||||||
|
from Interfaces.FormatModuleInterface import FormatModuleInterface
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
|
||||||
|
class MixFormat:
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
format:FormatModuleInterface,
|
||||||
|
options:Optional[dict[str, Any|None]] = None
|
||||||
|
) -> None:
|
||||||
|
self.format:FormatModuleInterface = format
|
||||||
|
self.capitalize:bool = bool(options and options.get("capitalized"))
|
||||||
|
|
||||||
|
def __get_separator_and_items(self:Self, i:int, inputs:str|list[Any|None]) -> tuple[str, list[str]]:
|
||||||
|
|
||||||
|
separator:str
|
||||||
|
original_items:list[str]
|
||||||
|
|
||||||
|
separator, original_items = (
|
||||||
|
(lambda _, separator, options:(
|
||||||
|
separator, str(options).split("|")
|
||||||
|
))(*RE.BASIC_MODE_SPLIT.match(inputs).groups()) if Check.is_string(inputs) else
|
||||||
|
inputs if Check.is_array(inputs) else
|
||||||
|
(None, None))
|
||||||
|
|
||||||
|
return separator, self.format.get_list(i, original_items)
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
i:int,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:
|
||||||
|
|
||||||
|
separator:str
|
||||||
|
items:list[str]
|
||||||
|
l:int
|
||||||
|
results:str
|
||||||
|
|
||||||
|
separator, items = self.__get_separator_and_items(i, inputs)
|
||||||
|
l = len(items)
|
||||||
|
|
||||||
|
Utils.randomize_array(items)
|
||||||
|
results = self.format.execute(i, (
|
||||||
|
"".join(items) if l < 2 else
|
||||||
|
", ".join(items[:l - 1]) + (
|
||||||
|
" " if not separator else
|
||||||
|
" " + separator.strip() + " " if RE.IS_SEPARATOR.match(separator) else
|
||||||
|
separator) + items[l - 1]), shared, fragments)
|
||||||
|
|
||||||
|
return RE.CAPITAL_CASE.sub(lambda matches:(
|
||||||
|
matches.group(1).upper()
|
||||||
|
), results) if self.capitalize else results
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> int:
|
||||||
|
|
||||||
|
separator:str
|
||||||
|
items:list[str]
|
||||||
|
l:int
|
||||||
|
|
||||||
|
separator, items = self.__get_separator_and_items(i, inputs)
|
||||||
|
l = len(items)
|
||||||
|
|
||||||
|
return self.format.check_select(i, string, ((l, l), separator, items), shared, fragments)
|
||||||
|
|
||||||
44
Python/Modules/Format/PlainFormat.py
Normal file
44
Python/Modules/Format/PlainFormat.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Optional
|
||||||
|
from Interfaces.FormatModuleInterface import FormatModuleInterface
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
from Utils.Check import Check
|
||||||
|
|
||||||
|
class PlainFormat:
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
format:FormatModuleInterface,
|
||||||
|
options:Optional[dict[str, Any|None]] = None
|
||||||
|
) -> None:
|
||||||
|
self.format:FormatModuleInterface = format
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
i:int,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:
|
||||||
|
return self.format.execute(i, (
|
||||||
|
inputs if Check.is_string(inputs) else
|
||||||
|
inputs[0] if Check.is_string(inputs[0]) else
|
||||||
|
""), shared, fragments)
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> int:
|
||||||
|
|
||||||
|
substring:str = self.format.set_fragments_level((
|
||||||
|
inputs if Check.is_string(inputs) else
|
||||||
|
inputs[0] if Check.is_string(inputs[0]) else
|
||||||
|
""), fragments)
|
||||||
|
has_variables:bool = RE.FRAGMENT_VARIABLES.search(substring) is not None
|
||||||
|
|
||||||
|
return (
|
||||||
|
self.format.get_check_length(i, string, substring, shared, fragments, False) if has_variables else
|
||||||
|
self.format.prepare_result(string, substring, shared))
|
||||||
57
Python/Modules/Format/RandomFormat.py
Normal file
57
Python/Modules/Format/RandomFormat.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Optional
|
||||||
|
from Interfaces.FormatModuleInterface import FormatModuleInterface
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
|
||||||
|
class RandomFormat:
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
format:FormatModuleInterface,
|
||||||
|
options:Optional[dict[str, Any|None]] = None
|
||||||
|
) -> None:
|
||||||
|
self.format:FormatModuleInterface = format
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
i:int,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:
|
||||||
|
return self.format.execute(i, Utils.get_random(self.format.get_list(i, (
|
||||||
|
inputs.split("|") if Check.is_string(inputs) else
|
||||||
|
inputs[0] if Check.is_array(inputs[0]) else
|
||||||
|
""))), shared, fragments)
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> int:
|
||||||
|
|
||||||
|
has_empty:bool = False
|
||||||
|
option:str
|
||||||
|
|
||||||
|
for option in self.format.get_list(i, (
|
||||||
|
inputs.split("|") if Check.is_string(inputs) else
|
||||||
|
inputs[0] if Check.is_array(inputs[0]) else
|
||||||
|
"")):
|
||||||
|
if option == "":
|
||||||
|
if not has_empty:
|
||||||
|
has_empty = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
if RE.FRAGMENT_VARIABLES.match(self.format.set_fragments_level(option, fragments)):
|
||||||
|
return self.format.get_check_length(i, string, option, shared, fragments, False)
|
||||||
|
|
||||||
|
length:int = self.format.prepare_result(string, option, shared)
|
||||||
|
|
||||||
|
if length != -1:
|
||||||
|
return length
|
||||||
|
|
||||||
|
return 0 if has_empty else -1
|
||||||
48
Python/Modules/Format/RangeFormat.py
Normal file
48
Python/Modules/Format/RangeFormat.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Optional
|
||||||
|
from Interfaces.FormatModuleInterface import FormatModuleInterface
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
|
||||||
|
class RangeFormat:
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
format:FormatModuleInterface,
|
||||||
|
options:Optional[dict[str, Any|None]] = None
|
||||||
|
) -> None:
|
||||||
|
self.format:FormatModuleInterface = format
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
i:int,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:
|
||||||
|
|
||||||
|
inputs = (
|
||||||
|
[
|
||||||
|
int(value) for value in str(Utils.get_random(inputs.split("|"))).split("-")
|
||||||
|
] if Check.is_string(inputs) else
|
||||||
|
inputs if Check.is_array(inputs) else
|
||||||
|
[])
|
||||||
|
if Check.is_number(inputs):
|
||||||
|
return str(inputs)
|
||||||
|
|
||||||
|
l = len(inputs)
|
||||||
|
|
||||||
|
return str(
|
||||||
|
None if not l else
|
||||||
|
inputs[0] if l == 1 else
|
||||||
|
Utils.get_random(*inputs))
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> int:
|
||||||
|
return self.format.check_range(string, inputs)
|
||||||
94
Python/Modules/Format/SelectFormat.py
Normal file
94
Python/Modules/Format/SelectFormat.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Optional
|
||||||
|
from Interfaces.FormatModuleInterface import FormatModuleInterface
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
|
||||||
|
class SelectFormat:
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
format:FormatModuleInterface,
|
||||||
|
options:Optional[dict[str, Any|None]] = None
|
||||||
|
) -> None:
|
||||||
|
self.format:FormatModuleInterface = format
|
||||||
|
self.capitalize:bool = bool(options and options.get("capitalized"))
|
||||||
|
|
||||||
|
def __get_separator_and_items(self:Self, i:int, inputs:str|list[Any|None]) -> tuple[tuple[int, int], str, list[str]]:
|
||||||
|
|
||||||
|
range:tuple[int, int]
|
||||||
|
separator:str
|
||||||
|
original_items:list[str]
|
||||||
|
|
||||||
|
separator, original_items = (
|
||||||
|
(lambda _, range, separator, options:(
|
||||||
|
tuple(int(value) for value in range.split("-")), separator, str(options).split("|")
|
||||||
|
))(*RE.SELECT_MODE_SPLIT.match(inputs).groups()) if Check.is_string(inputs) else
|
||||||
|
inputs if Check.is_array(inputs) else
|
||||||
|
(None, None, None))
|
||||||
|
|
||||||
|
return range, separator, self.format.get_list(i, original_items)
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
i:int,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:
|
||||||
|
|
||||||
|
range:tuple[int, int]
|
||||||
|
separator:str
|
||||||
|
items:list[str]
|
||||||
|
|
||||||
|
range, separator, items = self.__get_separator_and_items(i, inputs)
|
||||||
|
k = Utils.get_random(*range)
|
||||||
|
|
||||||
|
if not k:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
l:int = len(items)
|
||||||
|
results:str
|
||||||
|
|
||||||
|
if l < 2:
|
||||||
|
results = "".join(items)
|
||||||
|
else:
|
||||||
|
|
||||||
|
Utils.randomize_array(items)
|
||||||
|
items = items[:k]
|
||||||
|
l = len(items)
|
||||||
|
|
||||||
|
results = (
|
||||||
|
items[0] if l < 2 else
|
||||||
|
", ".join(items[:l - 1]) + (
|
||||||
|
" " if not separator else
|
||||||
|
" " + separator.strip() + " " if RE.IS_SEPARATOR.match(separator) else
|
||||||
|
separator) + items[l - 1])
|
||||||
|
|
||||||
|
results = self.format.execute(i, results, shared, fragments)
|
||||||
|
|
||||||
|
return RE.CAPITAL_CASE.sub(lambda matches:(
|
||||||
|
matches.group(1).upper()
|
||||||
|
), results) if self.capitalize else results
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> int:
|
||||||
|
|
||||||
|
minimum:int
|
||||||
|
maximum:int
|
||||||
|
separator:str
|
||||||
|
items:list[str]
|
||||||
|
l:int
|
||||||
|
|
||||||
|
(minimum, maximum), separator, items = self.__get_separator_and_items(i, inputs)
|
||||||
|
|
||||||
|
return self.format.check_select(i, string, (
|
||||||
|
(minimum, maximum), separator, items
|
||||||
|
), shared, fragments)
|
||||||
|
|
||||||
66
Python/Modules/Format/SerieFormat.py
Normal file
66
Python/Modules/Format/SerieFormat.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Self, Any, Optional
|
||||||
|
from Interfaces.FormatModuleInterface import FormatModuleInterface
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
|
||||||
|
class SerieFormat:
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
format:FormatModuleInterface,
|
||||||
|
options:Optional[dict[str, Any|None]] = None
|
||||||
|
) -> None:
|
||||||
|
self.format:FormatModuleInterface = format
|
||||||
|
|
||||||
|
def get(self:Self,
|
||||||
|
i:int,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:
|
||||||
|
|
||||||
|
inputs = (
|
||||||
|
[
|
||||||
|
int(value) for value in str(Utils.get_random(inputs.split("|"))).split("-")
|
||||||
|
] if Check.is_string(inputs) else
|
||||||
|
inputs if Check.is_array(inputs) else
|
||||||
|
[])
|
||||||
|
serie:int|None = shared.get("serie")
|
||||||
|
range:int|list[int]|list[int, int]
|
||||||
|
|
||||||
|
if serie is not None:
|
||||||
|
inputs = [range for range in inputs if (
|
||||||
|
serie < range if not Check.is_array(range) else
|
||||||
|
serie < range[0] if len(range) == 1 else
|
||||||
|
serie < range[1])]
|
||||||
|
|
||||||
|
range = Utils.get_random(*inputs)
|
||||||
|
|
||||||
|
if not Check.is_array(range):
|
||||||
|
shared["serie"] = range
|
||||||
|
return str(range)
|
||||||
|
if len(range) == 1:
|
||||||
|
shared["serie"] = range[0]
|
||||||
|
return str(range[0])
|
||||||
|
|
||||||
|
value:int
|
||||||
|
|
||||||
|
while True:
|
||||||
|
value = Utils.get_random(*range)
|
||||||
|
if value > serie:
|
||||||
|
break
|
||||||
|
serie = value
|
||||||
|
|
||||||
|
return str(value)
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
inputs:str|list[Any|None],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> int:
|
||||||
|
return self.format.check_range(string, inputs)
|
||||||
310
Python/Modules/FormatModule.py
Normal file
310
Python/Modules/FormatModule.py
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from Interfaces.OpoTestsInterface import OpoTestsInterface
|
||||||
|
from typing import Self, Any
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
from Utils.Check import Check
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
from re import Match as REMatch
|
||||||
|
from Interfaces.FormatModeInterface import FormatModeInterface
|
||||||
|
from Modules.Format.CapitalizeFormat import CapitalizeFormat
|
||||||
|
from Modules.Format.MixFormat import MixFormat
|
||||||
|
from Modules.Format.PlainFormat import PlainFormat
|
||||||
|
from Modules.Format.RandomFormat import RandomFormat
|
||||||
|
from Modules.Format.RangeFormat import RangeFormat
|
||||||
|
from Modules.Format.SelectFormat import SelectFormat
|
||||||
|
from Modules.Format.SerieFormat import SerieFormat
|
||||||
|
|
||||||
|
class FormatModule:
|
||||||
|
|
||||||
|
def __init__(self:Self, op:OpoTestsInterface) -> None:
|
||||||
|
self.op:OpoTestsInterface = op
|
||||||
|
self.modes:dict[str, FormatModeInterface] = {}
|
||||||
|
|
||||||
|
for keys, mode in (
|
||||||
|
(("capitalize", "cap", "capital", "Cap", "Capitalize", "Capital"), CapitalizeFormat(self)),
|
||||||
|
(("mix", "mixin"), MixFormat(self)),
|
||||||
|
(("Mix", "Mixin"), MixFormat(self, {"capitalized" : True})),
|
||||||
|
(("plain",), PlainFormat(self)),
|
||||||
|
(("rand", "random"), RandomFormat(self)),
|
||||||
|
(("range",), RangeFormat(self)),
|
||||||
|
(("select",), SelectFormat(self)),
|
||||||
|
(("Select",), SelectFormat(self, {"capitalized" : True})),
|
||||||
|
(("serie",), SerieFormat(self)),
|
||||||
|
):
|
||||||
|
for key in keys:
|
||||||
|
self.modes[key] = mode
|
||||||
|
|
||||||
|
def start(self:Self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_fragments_level(string:str, fragments:list[str]) -> str:
|
||||||
|
return RE.FRAGMENT_PATTERN.sub(lambda matches:fragments[int(matches.group(1))], string)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __build_fragment(matches:REMatch, fragments:list[str]) -> str:
|
||||||
|
fragments += [matches.group(1)]
|
||||||
|
return "$$$" + str(len(fragments) - 1) + "$$$"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def build_fragments(cls:type[Self], string:str, fragments:list[str] = []) -> str:
|
||||||
|
return cls.set_fragments_level(Utils.recursive(string, lambda string:(
|
||||||
|
RE.FRAGMENT_VARIABLES.sub(lambda matches:(
|
||||||
|
cls.__build_fragment(matches, fragments)
|
||||||
|
), string)
|
||||||
|
)), fragments)
|
||||||
|
|
||||||
|
def __process_variable(self:Self,
|
||||||
|
i:int,
|
||||||
|
original:str,
|
||||||
|
key:str,
|
||||||
|
shared:dict[str, Any|None],
|
||||||
|
fragments:list[str]
|
||||||
|
) -> str:
|
||||||
|
if Check.is_key(key):
|
||||||
|
if key in shared:
|
||||||
|
return str(shared[key])
|
||||||
|
|
||||||
|
variable:list[Any|None] = self.op.questions.get_value(key, i)
|
||||||
|
method:str
|
||||||
|
data:list[Any|None]
|
||||||
|
|
||||||
|
if variable is not None:
|
||||||
|
method, *data = variable
|
||||||
|
if method in self.modes:
|
||||||
|
return self.modes[method].get(i, data, shared, fragments)
|
||||||
|
else:
|
||||||
|
|
||||||
|
matches:REMatch|None = RE.FORMAT_SPLIT.match(key)
|
||||||
|
|
||||||
|
if matches:
|
||||||
|
method, *data = matches.groups()[1:3]
|
||||||
|
if method in self.modes:
|
||||||
|
return self.modes[method].get(i, data, shared, fragments)
|
||||||
|
return original
|
||||||
|
|
||||||
|
def __execute_varibles(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
shared:dict[str, Any|None],
|
||||||
|
fragments:list[str]
|
||||||
|
) -> str:
|
||||||
|
try:
|
||||||
|
return RE.FRAGMENT_VARIABLES.sub(lambda matches:(
|
||||||
|
self.__process_variable(i, *matches.groups()[0:2], shared, fragments)
|
||||||
|
), string)
|
||||||
|
except Exception as exception:
|
||||||
|
print(exception)
|
||||||
|
return string
|
||||||
|
|
||||||
|
def execute(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str:
|
||||||
|
return Utils.recursive(self.build_fragments(string, fragments), lambda string:(
|
||||||
|
self.__execute_varibles(i, string, shared, fragments)
|
||||||
|
))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def prepare_result(string:str, option:str, shared:dict[str, Any|None]) -> int:
|
||||||
|
if string.lower().startswith(option.lower()):
|
||||||
|
if "capitalized" not in shared or shared["capitalized"]:
|
||||||
|
shared["capitalized"] = False
|
||||||
|
return len(option)
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def check(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
options:str|list[str],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = [],
|
||||||
|
check_full:bool = True
|
||||||
|
) -> tuple[bool, int]:
|
||||||
|
|
||||||
|
length:int = 0
|
||||||
|
option:str
|
||||||
|
ok:bool = True
|
||||||
|
|
||||||
|
string = string.lower()
|
||||||
|
|
||||||
|
for option in Utils.get_array(options):
|
||||||
|
|
||||||
|
clone:str = "" + string
|
||||||
|
option_fragmented:str = self.build_fragments(option, fragments)
|
||||||
|
i:int = 0
|
||||||
|
|
||||||
|
length = 0
|
||||||
|
while True:
|
||||||
|
|
||||||
|
matches:REMatch|None = RE.FORMAT_PARTS.search(option_fragmented)
|
||||||
|
|
||||||
|
if not matches:
|
||||||
|
break
|
||||||
|
|
||||||
|
part:str = matches.group(0)
|
||||||
|
m:int = -1
|
||||||
|
key:str = matches.group(1)
|
||||||
|
method:str
|
||||||
|
data:list[Any|None]
|
||||||
|
|
||||||
|
if key:
|
||||||
|
if Check.is_key(key):
|
||||||
|
method, *data = self.op.questions.get_value(key, i)
|
||||||
|
if method in self.modes:
|
||||||
|
m = self.modes[method].check(i, clone, data, shared, fragments, clone, check_full)
|
||||||
|
|
||||||
|
# JS FormatModule lines 174-177.
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
submatches:REMatch|None = RE.FORMAT_SPLIT.match(key)
|
||||||
|
|
||||||
|
if submatches:
|
||||||
|
|
||||||
|
method, *data = submatches.groups()[1:3]
|
||||||
|
|
||||||
|
if method in self.modes:
|
||||||
|
m = self.modes[method].check(i, clone, data, shared, fragments, clone, check_full)
|
||||||
|
|
||||||
|
if m == -1:
|
||||||
|
m = self.prepare_result(clone, part, shared)
|
||||||
|
|
||||||
|
if m != -1:
|
||||||
|
clone = clone[m:]
|
||||||
|
length += m
|
||||||
|
continue
|
||||||
|
ok = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if ok:
|
||||||
|
ok = not check_full or not len(clone)
|
||||||
|
if ok:
|
||||||
|
break
|
||||||
|
|
||||||
|
return (ok, length)
|
||||||
|
|
||||||
|
def get_check_length(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
options:str|list[str],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = [],
|
||||||
|
check_full:bool = True
|
||||||
|
) -> int:
|
||||||
|
|
||||||
|
has:bool
|
||||||
|
length:int
|
||||||
|
|
||||||
|
has, length = self.check(i, string, options, shared, fragments, check_full)
|
||||||
|
|
||||||
|
return length if has else -1
|
||||||
|
|
||||||
|
def check_select(self:Self,
|
||||||
|
i:int,
|
||||||
|
string:str,
|
||||||
|
options:tuple[tuple[int, int], str, list[str]],
|
||||||
|
shared:dict[str, Any|None] = {},
|
||||||
|
fragments:list[str] = []
|
||||||
|
) -> str|None:
|
||||||
|
|
||||||
|
length:int = 0
|
||||||
|
k:int = 0
|
||||||
|
check_last:bool = False
|
||||||
|
minimum:int
|
||||||
|
maximum:int
|
||||||
|
separator:str
|
||||||
|
items:list[str]
|
||||||
|
separator_length:int
|
||||||
|
|
||||||
|
(minimum, maximum), separator, items = options
|
||||||
|
separator_length = len(separator)
|
||||||
|
|
||||||
|
while k < maximum:
|
||||||
|
|
||||||
|
ok:bool = False
|
||||||
|
l:int = len(items)
|
||||||
|
j:int
|
||||||
|
item:str
|
||||||
|
|
||||||
|
if check_last or (k and k == l - 1):
|
||||||
|
if not string.startswith(" " + separator + " "):
|
||||||
|
return -1
|
||||||
|
|
||||||
|
length += separator_length + 2
|
||||||
|
string = string[0, separator_length + 2]
|
||||||
|
|
||||||
|
for j, item in enumerate(items):
|
||||||
|
|
||||||
|
has_variables:bool = RE.FRAGMENT_VARIABLES.match(
|
||||||
|
self.set_fragments_level(item, shared, fragments)
|
||||||
|
) is not None
|
||||||
|
item_length:int = (
|
||||||
|
self.get_check_length(i, string, [item], shared, fragments, False) if has_variables else
|
||||||
|
self.prepare_result(string, item, shared))
|
||||||
|
|
||||||
|
if item_length != -1:
|
||||||
|
string = string[:item_length]
|
||||||
|
items = items[:j] + items[j + 1:]
|
||||||
|
length += item_length
|
||||||
|
ok = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if ok:
|
||||||
|
if "capitalized" not in shared or shared["capitalized"]:
|
||||||
|
shared["capitalized"] = False
|
||||||
|
elif check_last or not k:
|
||||||
|
return -1
|
||||||
|
else:
|
||||||
|
check_last = True
|
||||||
|
k -= 1
|
||||||
|
|
||||||
|
return -1 if k < minimum else length
|
||||||
|
|
||||||
|
def __get_list_items(self:Self, i:int, item:str) -> list[str]:
|
||||||
|
matches:REMatch|None = RE.LIST_ITEM.match(item)
|
||||||
|
|
||||||
|
if matches:
|
||||||
|
|
||||||
|
key:str = matches.group(1)
|
||||||
|
method:str
|
||||||
|
list_items:list[str]
|
||||||
|
|
||||||
|
method, *list_items = self.op.questions.get_value(key, i)
|
||||||
|
|
||||||
|
if method == "list":
|
||||||
|
return list_items
|
||||||
|
return [item]
|
||||||
|
|
||||||
|
def get_list(self:Self, i:int, items:list[str]) -> list[str]:
|
||||||
|
return [subitem for item in items for subitem in self.__get_list_items(i, item)]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_range(string:str, inputs:str|list[str]) -> int:
|
||||||
|
|
||||||
|
number_matches:REMatch|None = RE.ABSOLUTE_INTEGER.match(string)
|
||||||
|
|
||||||
|
if number_matches:
|
||||||
|
|
||||||
|
number:int = int(string)
|
||||||
|
|
||||||
|
for range in (
|
||||||
|
[
|
||||||
|
int(value) for value in str(Utils.get_random(inputs.split("|"))).split("-")
|
||||||
|
] if Check.is_string(inputs) else
|
||||||
|
inputs if Check.is_array(inputs) else
|
||||||
|
[]):
|
||||||
|
if Check.is_number(range):
|
||||||
|
if number == range:
|
||||||
|
return len(string)
|
||||||
|
elif len(range) == 1:
|
||||||
|
if number == range[0]:
|
||||||
|
return len(string)
|
||||||
|
else:
|
||||||
|
if number >= range[0] and number <= range[1]:
|
||||||
|
return len(string)
|
||||||
|
return -1
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from Utils.Patterns import RE
|
from Utils.Patterns import RE
|
||||||
from typing import Any, Optional, Self
|
from typing import Any, Optional, Self
|
||||||
@ -19,4 +20,24 @@ class Check:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_array(item:Optional[Any]) -> bool:
|
def is_array(item:Optional[Any]) -> bool:
|
||||||
return isinstance(item, (list, tuple))
|
return isinstance(item, (list, tuple))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_integer(item:Optional[Any]) -> bool:
|
||||||
|
return isinstance(item, int)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_float(item:Optional[Any]) -> bool:
|
||||||
|
return isinstance(item, float)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_number(item:Optional[Any]) -> bool:
|
||||||
|
return isinstance(item, (int, float))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_bytes(item:Optional[Any]) -> bool:
|
||||||
|
return isinstance(item, bytes)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_json_object(item:Optional[Any]) -> bool:
|
||||||
|
return isinstance(item, (dict, list, tuple))
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from re import Pattern as REPattern
|
from re import Pattern as REPattern
|
||||||
from re import compile as re_compile
|
from re import compile as re_compile
|
||||||
@ -10,4 +11,22 @@ class RE:
|
|||||||
LINE:REPattern = re_compile(r'^([^\r\n]*)')
|
LINE:REPattern = re_compile(r'^([^\r\n]*)')
|
||||||
SLASHES:REPattern = re_compile(r'[\\/]+')
|
SLASHES:REPattern = re_compile(r'[\\/]+')
|
||||||
EXCEPTION:REPattern = re_compile(r'^\s*File "([^"]+)", line ([0-9]+), in ([^\n]+)(.*|[\r\n]*)*$')
|
EXCEPTION:REPattern = re_compile(r'^\s*File "([^"]+)", line ([0-9]+), in ([^\n]+)(.*|[\r\n]*)*$')
|
||||||
BREAK_LINES:REPattern = re_compile(r'\r\n|[\r\n]')
|
BREAK_LINES:REPattern = re_compile(r'\r\n|[\r\n]')
|
||||||
|
TO_SNAKE:REPattern = re_compile(r'[^a-zA-Z0-9]*([A-Z][A-Z0-9]*)|[^a-z0-9]+')
|
||||||
|
FRAGMENT_PATTERN:REPattern = re_compile(r'\${3}([0-9]+)\${3}')
|
||||||
|
FRAGMENT_VARIABLES:REPattern = re_compile(r'\{([^\{\}]+)\}')
|
||||||
|
FORMAT_SPLIT:REPattern = re_compile(r'^([^,:]+)[,:](.*)$')
|
||||||
|
FORMAT_PARTS:REPattern = re_compile(r'\{([^\{\}]+)\}|[^\{]+|\{')
|
||||||
|
LIST_ITEM:REPattern = re_compile(r'^list:([a-z0-9_]+)$', RE_IGNORE_CASE)
|
||||||
|
CAPITAL_CASE:REPattern = re_compile(r'^(.)')
|
||||||
|
BASIC_MODE_SPLIT:REPattern = re_compile(r'^([^,]+),(.*)$')
|
||||||
|
IS_SEPARATOR:REPattern = re_compile(r'^[a-z 0-9]+$', RE_IGNORE_CASE)
|
||||||
|
ABSOLUTE_INTEGER:REPattern = re_compile(r'^[0-9]+$')
|
||||||
|
SELECT_MODE_SPLIT:REPattern = re_compile(r'^([^,]+),([^,]+),(.*)$')
|
||||||
|
ROUTE_ITEM:REPattern = re_compile(r'^(?:([^:]+):)([^\s]+)\s+(?:([^\@\s]+)\@([^\s]+)|([^\s]+))(?:\s+([^\s]+))?$')
|
||||||
|
ROUTE_RE_FORMAT:REPattern = re_compile(r'(\(\[\^\\\/\]\+\))|([\/])')
|
||||||
|
HTTP_BLOCKS:REPattern = re_compile(r'((?:(?!(?:(?:\r\n){2}|\n{2}|\r{2}))(?:.|[\r\n]+))+)(?:(?:\r\n){2}|\n{2}|\r{2}((?:.+|[\r\n]+)*))?')
|
||||||
|
NEW_LINE:REPattern = re_compile(r'\r\n|[\n\r]')
|
||||||
|
HTTP_REQUEST:REPattern = re_compile(r'^([^\s]+)\s([^\s\?\#]+)(?:\?([^#]+))?(?:\#[^\s]+)?\s([^\/]+)\/([0-9\.]+)$')
|
||||||
|
URI_VARIABLES:REPattern = re_compile(r'&?([^=&]+)=([^&]*)')
|
||||||
|
HEADER_LINE:REPattern = re_compile(r'^([^\:]+)\:(.+)$')
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from Utils.Check import Check
|
from Utils.Check import Check
|
||||||
from typing import Any, Self, Optional
|
from typing import Any, Self, Optional
|
||||||
@ -6,6 +7,11 @@ from Utils.Patterns import RE
|
|||||||
from re import Match as REMatch
|
from re import Match as REMatch
|
||||||
from inspect import stack as get_stack
|
from inspect import stack as get_stack
|
||||||
from inspect import FrameInfo
|
from inspect import FrameInfo
|
||||||
|
from json import loads as json_decode
|
||||||
|
from json import dumps as json_encode
|
||||||
|
from random import random as math_random
|
||||||
|
from base64 import b64decode as base64_decode
|
||||||
|
from base64 import b64encode as base64_encode
|
||||||
|
|
||||||
class Utils:
|
class Utils:
|
||||||
|
|
||||||
@ -80,4 +86,92 @@ class Utils:
|
|||||||
return [string for item in items for string in (
|
return [string for item in items for string in (
|
||||||
cls.get_strings(*item) if Check.is_array(item) else (item,)
|
cls.get_strings(*item) if Check.is_array(item) else (item,)
|
||||||
) if Check.is_string(string)]
|
) if Check.is_string(string)]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def json_encode(data:dict[str, Any|None]|list[Any|None]|tuple[Any|None]) -> str|None:
|
||||||
|
try:
|
||||||
|
return json_encode(data, ensure_ascii=False)
|
||||||
|
except Exception as exception:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def json_decode(data:str) -> dict[str, Any|None]|list[Any|None]|tuple[Any|None]|None:
|
||||||
|
try:
|
||||||
|
return json_decode(data)
|
||||||
|
except Exception as exception:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_snake(string:str) -> str:
|
||||||
|
|
||||||
|
def callback(matches:REMatch) -> str:
|
||||||
|
|
||||||
|
upper:str|None = matches.group(1)
|
||||||
|
|
||||||
|
return "_" + upper.lower() if upper else "_"
|
||||||
|
|
||||||
|
return RE.TO_SNAKE.sub(callback, string).lower()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def recursive(data:str, callback:Any) -> str:
|
||||||
|
|
||||||
|
cache:str = data
|
||||||
|
|
||||||
|
while True:
|
||||||
|
data = cache
|
||||||
|
cache = callback(cache)
|
||||||
|
if data == cache:
|
||||||
|
break
|
||||||
|
|
||||||
|
return cache
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_array(item:Any|None) -> list[Any|None]:
|
||||||
|
return item if Check.is_array(item) else [item]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_random(_from:Optional[int] = None, _to:Optional[int] = None) -> Any|None:
|
||||||
|
return (
|
||||||
|
math_random() if _from is None else
|
||||||
|
_from[int(math_random() * len(_from))] if Check.is_array(_from) else
|
||||||
|
(
|
||||||
|
int(math_random() * _from) if _to is None else
|
||||||
|
int(math_random() * (_to - _from) + _from) if Check.is_integer(_to) else
|
||||||
|
math_random() * (_to - float(_from)) + float(_from) if Check.is_float(_to) else
|
||||||
|
None) if Check.is_integer(_from) else
|
||||||
|
(
|
||||||
|
math_random() * _from if _to is None else
|
||||||
|
math_random() * (float(_to) - _from) + _from if Check.is_number(_to) else
|
||||||
|
None) if Check.is_float(_from) else
|
||||||
|
None)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def randomize_array(cls:type[Self], items:list[Any|None]) -> None:
|
||||||
|
|
||||||
|
l:int = len(items)
|
||||||
|
|
||||||
|
for i in range(l):
|
||||||
|
|
||||||
|
j:int = cls.get_random(l)
|
||||||
|
|
||||||
|
if i != j:
|
||||||
|
items[i], items[j] = items[j], items[i]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def base64_encode(data:str|bytes, encoding:str = "utf-8") -> str|None:
|
||||||
|
try:
|
||||||
|
return base64_encode(data.encode(encoding) if Check.is_string(data) else data).decode(encoding)
|
||||||
|
except Exception as exception:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def base64_decode(data:str|bytes, encoding:str = "utf-8", is_string:bool = True) -> str|bytes|None:
|
||||||
|
try:
|
||||||
|
decoded:bytes = base64_decode(data.encode(encoding) if Check.is_string(data) else data)
|
||||||
|
return decoded.decode(encoding) if is_string else decoded
|
||||||
|
except Exception as exception:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
@ -1,5 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from Application.OpoTests import OpoTests
|
from Application.OpoTests import OpoTests
|
||||||
|
from Controllers.TestController import TestController
|
||||||
|
|
||||||
opo_test:OpoTests = OpoTests()
|
opo_test:OpoTests = OpoTests()
|
||||||
|
opo_test.controllers.add({
|
||||||
|
"test" : TestController(opo_test)
|
||||||
|
})
|
||||||
Loading…
Reference in New Issue
Block a user