1+ import { onLoad } from '../../utils/utils' ;
12import { minizincUrl } from '../../vendors' ;
23
34declare const livecodes : {
45 minizinc : {
5- run : ( data : { dzn ?: string ; json ?: string ; config ?: MiniZincConfig } | 'init' ) => Promise < any > ;
6+ init : ( ) => Promise < void > ;
7+ solve : ( data ?: MiniZincData ) => any ;
8+ run : ( data ?: MiniZincData ) => Promise < any > ;
69 getSolvers : ( ) => Promise < string [ ] > ;
710 } ;
811} ;
@@ -18,101 +21,100 @@ interface MiniZincConfig {
1821 } ;
1922}
2023
21- let hasRun = false ;
22- const pageLoaded = new Promise ( ( resolve ) => {
23- if ( document . readyState === 'complete' || document . readyState === 'interactive' ) {
24- resolve ( undefined ) ;
25- } else {
26- window . addEventListener ( 'load' , resolve ) ;
27- }
28- } ) ;
24+ interface MiniZincData {
25+ dzn ?: string ;
26+ json ?: string ;
27+ config ?: MiniZincConfig ;
28+ }
2929
30+ let MiniZinc : any ;
31+ let hasRun = false ;
32+ const pageLoaded = new Promise ( ( resolve ) => onLoad ( resolve ) ) ;
3033const modPromise = import ( minizincUrl ) ;
3134
35+ const run = ( data : MiniZincData = { } ) => {
36+ if ( ! MiniZinc ) {
37+ throw new Error ( 'MiniZinc is not initialized. await livecodes.minizinc.init() first.' ) ;
38+ }
39+ hasRun = true ;
40+ if ( typeof data === 'string' ) data = { } ;
41+ const { dzn = '' , json = '' , config = { } } = data ;
42+ let code = '' ;
43+ const scripts = document . querySelectorAll ( 'script[type="text/minizinc"]' ) ;
44+ scripts . forEach ( ( script ) => ( code += script . innerHTML + '\n' ) ) ;
45+ const model = new MiniZinc . Model ( ) ;
46+ model . addFile ( 'playground.mzn' , code ) ;
47+ if ( dzn ) model . addFile ( 'playground.dzn' , dzn ) ;
48+ if ( json ) model . addFile ( 'playground.json' , json ) ;
49+ return model . solve ( {
50+ jsonOutput : config . jsonOutput ?? false ,
51+ options : {
52+ solver : 'gecode' ,
53+ 'time-limit' : 10000 ,
54+ ...config . options ,
55+ } ,
56+ } ) ;
57+ } ;
58+
3259livecodes . minizinc = {
33- run : async ( data : { dzn ?: string ; json ?: string ; config ?: MiniZincConfig } | 'init' = { } ) => {
34- if ( data === 'init' && hasRun ) return ;
35- const { dzn = '' , json = '' , config = { } } = data === 'init' ? { } : data ;
36- hasRun = true ;
60+ init : async ( ) => {
61+ if ( MiniZinc ) return ;
3762 await pageLoaded ;
38- let code = '' ;
39- const scripts = document . querySelectorAll ( 'script[type="text/minizinc"]' ) ;
40- scripts . forEach ( ( script ) => ( code += script . innerHTML + '\n' ) ) ;
41-
42- const MiniZinc = await modPromise ;
63+ MiniZinc = await modPromise ;
64+ } ,
65+ solve : ( data ) => run ( data ) ,
66+ run : async ( data ) => {
67+ await livecodes . minizinc . init ( ) ;
4368 return new Promise ( ( resolve ) => {
44- try {
45- const minizincConfig = config ;
46- const model = new MiniZinc . Model ( ) ;
47- model . addFile ( 'playground.mzn' , code ) ;
48- if ( dzn ) model . addFile ( 'playground.dzn' , dzn ) ;
49- if ( json ) model . addFile ( 'playground.json' , json ) ;
50-
51- const solve = model . solve ( {
52- jsonOutput : minizincConfig . jsonOutput ?? false ,
53- options : {
54- solver : 'gecode' ,
55- 'time-limit' : 10000 ,
56- ...minizincConfig . options ,
57- } ,
58- } ) ;
59-
60- const errors : any [ ] = [ ] ;
61- solve . on ( 'error' , ( error : any ) => {
62- // eslint-disable-next-line no-console
63- console . error ( error ) ;
64- errors . push ( error ) ;
65- } ) ;
66- solve . on ( 'exit' , ( msg : any ) => {
67- if ( msg . code === 0 ) return ;
68- if ( errors . length ) {
69- resolve ( {
70- status : 'ERROR' ,
71- errors,
72- } ) ;
73- } else {
74- resolve ( {
75- status : 'ERROR' ,
76- errors : [
77- {
78- type : 'error' ,
79- message : `Process finished with non-zero exit code ${ msg . code } .` ,
80- } ,
81- ] ,
82- } ) ;
83- }
84- } ) ;
85- solve . then ( ( result : any ) => {
86- const statusMap : any = {
87- ALL_SOLUTIONS : '==========' ,
88- OPTIMAL_SOLUTION : '==========' ,
89- UNSATISFIABLE : '=====UNSATISFIABLE=====' ,
90- UNSAT_OR_UNBOUNDED : '=====UNSATorUNBOUNDED=====' ,
91- UNBOUNDED : '=====UNBOUNDED=====' ,
92- UNKNOWN : '=====UNKNOWN=====' ,
93- ERROR : '=====ERROR=====' ,
94- } ;
95- const status = statusMap [ result . status ] || '' ;
96- const output =
97- result . solution ?. output ?. default ??
98- result . solution ?. output ?. dzn ??
99- result . solution ?. output ?. json ??
100- result . solution ?. output ?. raw ??
101- result . solution ?. output ??
102- '' ;
103- const msg = typeof output === 'string' ? output + status : output ;
104- // eslint-disable-next-line no-console
105- console . log ( msg ) ;
106- resolve ( result ) ;
107- } ) ;
108- } catch ( err ) {
69+ const solve = run ( data ) ;
70+ const errors : any [ ] = [ ] ;
71+ solve . on ( 'error' , ( error : any ) => {
72+ // eslint-disable-next-line no-console
73+ console . error ( error ) ;
74+ errors . push ( error ) ;
75+ } ) ;
76+ solve . on ( 'exit' , ( msg : any ) => {
77+ if ( msg . code === 0 ) return ;
78+ if ( errors . length ) {
79+ resolve ( {
80+ status : 'ERROR' ,
81+ errors,
82+ } ) ;
83+ } else {
84+ resolve ( {
85+ status : 'ERROR' ,
86+ errors : [
87+ {
88+ type : 'error' ,
89+ message : `Process finished with non-zero exit code ${ msg . code } .` ,
90+ } ,
91+ ] ,
92+ } ) ;
93+ }
94+ } ) ;
95+ solve . then ( ( result : any ) => {
96+ const statusMap : any = {
97+ ALL_SOLUTIONS : '==========' ,
98+ OPTIMAL_SOLUTION : '==========' ,
99+ UNSATISFIABLE : '=====UNSATISFIABLE=====' ,
100+ UNSAT_OR_UNBOUNDED : '=====UNSATorUNBOUNDED=====' ,
101+ UNBOUNDED : '=====UNBOUNDED=====' ,
102+ UNKNOWN : '=====UNKNOWN=====' ,
103+ ERROR : '=====ERROR=====' ,
104+ } ;
105+ const status = statusMap [ result . status ] || '' ;
106+ const output =
107+ result . solution ?. output ?. default ??
108+ result . solution ?. output ?. dzn ??
109+ result . solution ?. output ?. json ??
110+ result . solution ?. output ?. raw ??
111+ result . solution ?. output ??
112+ '' ;
113+ const msg = typeof output === 'string' ? output + status : output ;
109114 // eslint-disable-next-line no-console
110- console . error ( err ) ;
111- resolve ( {
112- status : 'ERROR' ,
113- errors : [ err ] ,
114- } ) ;
115- }
115+ console . log ( msg ) ;
116+ resolve ( result ) ;
117+ } ) ;
116118 } ) ;
117119 } ,
118120 getSolvers : async ( ) => {
@@ -121,10 +123,10 @@ livecodes.minizinc = {
121123 } ,
122124} ;
123125
124- if ( document . readyState === 'complete' || document . readyState === 'interactive' ) {
125- livecodes . minizinc . run ( ' init' ) ;
126- } else {
127- window . addEventListener ( 'load' , ( ) => {
128- livecodes . minizinc . run ( 'init' ) ;
126+ onLoad ( ( ) => {
127+ livecodes . minizinc . init ( ) . then ( ( ) => {
128+ // run only if user code has not called `run` or `solve`
129+ if ( hasRun ) return ;
130+ livecodes . minizinc . run ( ) ;
129131 } ) ;
130- }
132+ } ) ;
0 commit comments