phetsims / circuit-construction-kit-common

"Circuit Construction Kit: Basics" is an educational simulation in HTML5, by PhET Interactive Simulations.
GNU General Public License v3.0
10 stars 10 forks source link

Save & Load #151

Open samreid opened 8 years ago

samreid commented 8 years ago

We would like to have save and load without having to rely on phet-io. Query parameters seems like the simplest way to do this from the user's standpoint. But we would need to choose a sparse data representation, possibly rounding off the floating point numbers and compressing it, then we may still have problems in browsers like IE with a small number of query parameters. This will be for the DC version.

samreid commented 8 years ago

@kathy-phet said it would be good to support file:// for this as well.

samreid commented 8 years ago

@arouinfar @kathy-phet @ariel-phet Are we going to save view options as well (such as whether electrons are shown or hidden), or just the state of the circuit?

samreid commented 8 years ago

Here's one of the longest circuits I can think of:

image

Everything is at a slight angle so there is no redundancy in the coordinates. The length of the JSON is 7274 characters, well above the established limit of 2048 characters. However, compression with LZString brings this down to 1493 characters. When I tried these characters in the URL, it makes Chrome's address bar very sluggish:

"㞂⃮ॠ上惎‗Ƶ䬸丁瀡胬ر褀᠃ꄲ脘١ꁖᨄถͥ撷ᨐ悀ෂᘀ麤⭔ᶇᐬÔ挩考준♁ヰij冻戚Ž獵舿ᅙ鑉啣ꚕᵬ㥐閯錛ꂰ똸ꒌꈹ᎕ʮ㊉阖鈇ẈƱ몒妇▵邭ꊡㄔ岳蜀㬉⬃ޅ紉ຽጅ䜈慨蒴ꎼ蠢艖牢ι醢僇㴕趆ᅃꥌ獅唅亻അ䭉ἀ腬佳鱒ꪠ칛穘流䕴�녑쾪嫽ἵ櫝഻绸睂힯팺顒묌룇Ⓡ명灏䁹䕨잩릘ᰖ⾒海ꉀ㬤芪贲ꃄ㋆ᇗ낔暯覨솢ᕟૃ毱უ鸧ƹ㕪䲇ዲ㍇볎鏣�ᨛ鮊췛抺뢲걏ꁉᑓ糂鮅⩯閄펞贚Ꞔ외⪬暊ꎫ졆殁㫖뺰坶㝓춫劣ꛙ傘븋殛阓嗲떧睸㫨⺄ﯶꚗ挀⭁妲᫴⚞ꇭ᰸믹蒡뜓푌䊰ꡔ듟ꍕ썦喼ⱺ뜎픘㠂ꕥ鵤櫦京헫ዚ䚼�堜檃-�ʑၯ떎颷馂䗊ㄨꬤ狦㩛徖챳꫅篞⯟㱏汰躎塕⼥헛궺⛃蕢鬾炤ꆪ汯ৢ䁬ḕ࡚꫿蚯�䰉ù題ᵠ˪ࠀᆎց⑐ЏĠꠈؠö 글Θ鑌᨞䩡䎎ꝛ䌓茱䠫፸鉭多ꀯᓄ녬畩煮芽씧炝륡艒齇䦂沔ㅐ᱂鵙僜撝꒩멚鹈砚戋䅩籀颁ঀ疚⒁昕ħ処厒ڏ譤갎亜鹰ᗅ脾掚ꚹ햰此悇䑀豀ť耀䈀⮝၄
㠞髸搽Ėᆔㆸ뮄ቓ閕喘鞹㪓䃕锕啘胨靕㹅ꍔ茵뵚첔씦밮㚵䌥ꭧ록泓ퟍ昂꒵訣睒퐥୻偨〫糇㟭ᭀ퇥‛৔햭픕ᷓ澪矝Ź⫊�薏蒍㑔ౕ儳寗둽햣ⷷ洠�࿆گ衶緞䰶㞽�觃樸膝쿣累䍪໵ഭ齂餻櫗ྮ䌾楏䎯氾䴣㋍ꍴ腾铎㗍ﴶ懰铉㸻玽糫杸뽂褁怄♑䒠罘薐䁄်ɹⴙ໡灴╅䲐쪠褑倔ᴉ褰↲໯醘뚙෡�㦼댆븋夐´⬅屸᦮⍈跐幽컭늆㐷蓒︠⑁橻ఓ䥫퀜뎂闇먓́遥쿫⮲玎ᆞ䓶Ꞷ썔贴Ⴋ卦⬣ꁐ﵊췀᧡螉牄䴡덑蘜ꌎ檴㨉碀㓥㈏�綳ퟗ睶쬰唪웠砵܇㸄轓ヽ啅雒ǣ逅᫖ċཥ뭼ﶳ濸뤋뫉禚諙祄ꦋͤ㨑᤟࿮惜ᤀຩ애䝔諁ꤓ�î᡿芧꣇툄坰쟠瞆ၶ捷៨ၰ겦恌ᜡ켗เ㨓蜰築鵴㙷簳쓘뭑쌂혵둠䧑ૐ㓢ㅸ当鱤ᶓຉ렷Ť찳ᆐ⼩鼁ኆ呅ዉ䐌᲎减䠚쁻鞷졺僕虀桛鰛桝ઍꎽ胳쟡죝ᢣ偕ꊦ︅鋏᠙蠸㰌梬ᗀє腨艈�噇瑋홼�梚褃ꓰհ씐톝깆ꁊ⹸灌ዠᔦ⛞ᔰ㭕狯儂絎炍☄㭸錼導ॊ䉄秄譃㥐橲鲩ퟁ㒻䙁⾽⊨춗⎠蕁䇭щꢌ魠씱斢ﱣ迶椘㬆抙儖岣಩ধᢍ�슜ᚋ꘠უ㨣虑뀹쌋낙漭扬琑짊먣塐㳆퀻䜼뾭摆씗ঝ뉰ꆳ쯈鱳琨瓡Ḁ挆᳚Ⓣ蛘வ赤ᕋ菿ᗤᄒ崩��쌳᠜側ꏹ疵갊蓱蒲批뗙䆌ꑡ੕밈ࡡↁ�餅僤褺犛䋉ᅨ皌喹퓰ᜟ੪뼫走좉悲ୃ௪⮏㚐㠱哓豹ꁔ㊬몆᭖㐃蕖ೇ馻灙䪂驆Ⴎ됞�먑볱꜎털喲㊯쎼ꕙ釁⤘艡枇膩틐ಀꁁ䦬늓�ᘉ棃⫄愰룳梶䆄ꨛ⛘�뒀㌁栟ꛋ墲鎅糎ᓁᑮ謮悴糂ଘմ䲤뽥퐻チ邁컄�岂∔颌㻒ꂺ型垻蘼Ǖ戲ၑ鋨ⲡ놙좯쭢�百﵎ઢ떁屙㯄ࠑ鎆ëꐺಘ㰁튢ﳊ뉑ᬧꢈ쯈웹ᷝ㘆ჽܾ�詈뱫婲ﰅ팓ꃯཀ䱧h呮犢鼔䛭㬆㲐⻓ཏ㤵漉༰ꪏ˸Ნ◾ᥢ輹壙裤锕쏎ᾪ⎸⾎깔ꃊ灦㭁䉘콱ᚅ莊ﳘ﫸⹅䇎즏DŽ頪瘭ߪ躸徭櫓ற䄸亖홸ᦊ롳耱᷌械圞䟳̇鰩五짍퀙�䔌䴺ꏀꐽ삩舖Ᏻ엏⛭蠓븠䌭㬪៛嫀ɪᩋᏚ虇桪⣤ᦥ쏨쀘㼭嶌Ê亚舙⋬නᆠ≸眉崮巵ಫ⣤魗ư夔⻕撴ह裧⾜ꄾḷ칄䍖舰펼纯룻䇡猇涎堛థ⫁兣皠ఐᘪ련㭄⯳ر뛡坭爳綠靬귬懎棢뀢룿鍊䡢㚇묽ꢔ牁䋚뻦飱⼵轖⤷睝⻎뭮뙓͜⫨✛㢜푴ዢ⧊座ꪽ딛喙凖儾㲤コ⢠軜䲼⠈萵蹸డ녳㌆恕㲗✯豭䌵᫝ᕎ狠蚈᪦꘶퐳⚿큇걻ªׅꎂꍿ氊㛬猍硳渫�璅꠺겙獍덲㚎癃珶۵묛坊瞣쯐靬躺ꉛ뿫烅졤뉃櫑ᡛ୤閻晚ૣ�憞⑵漏�皿᳞蚩껫觠둴簓췣↔ꃇ獆媊缞�ଧى韃ᝰ湡풂鳠셋핮也㋒�죐௫䇠沙蘡䍫㻭᥾乳繇䲖튢鍣䘾憛䚛௫쾯鵮⋬ᩫꋾ擷喝꺓넰퓷㇍⬜〯㢶⏀貌ꠛຈ눩ၔ쫆ᮥ亹磩⨵슎ᢁ沞巡㺉⻦縃﫥䴶ꆏҫ챬㪵⧎펤肉ⷜ뻳챣눭泼၍⍐餪튥ⶼ䈍ͬ㠐ꨞ昪〧뺮⛒攩㘭ᵡ暵斣蛥Ḁ옧깜縎梁ꇞ辪諨謦雨虪忏㠮쳀翤櫧樨걮ċ語뿅쩆꤉ゲ艖�搁셖츙ʮᔁ氮舡칔Ắᠽꏖ샬쉾棦䉬茊ᐕ捨尒⋭ꢺ窘賐將昰ꛮ됦蚎홭汫⵼ﳥ뉲⣦븭乹带㑰⤎컂탤ↁ뚤䊩旸쬏麎Ἴ�멍ୀ픋ᛌ曪괙쉜ૐ捦�Ⱄ鲇㧀툧捥䲠攚闅䋦◲᫬ꊉꚢ귍䙏쭺줓퇛ದ矃⛈ꓶ壩ኈ짅ꅍर张峑ྡ徤큉ⵆLJዞ鋄澘ಪ좳苊餛Ѐ�"

So I'm not sure whether this will be practical or not.

samreid commented 8 years ago

Also, I'm not sure if all browsers support that character set in the address bar.

samreid commented 8 years ago

Using compress to URI component (better for URLs), I see:

z.length 7274

LZString.compressToEncodedURIComponent(z).length 3979

So this is a bit out of bounds for IE. Perhaps we should check URL limits for browsers again and see if 2048 is still a good limit.

samreid commented 8 years ago

It looks like many browsers support longer URLs now, including Edge, so we could give this a try as an implementation for save/load. If this is too flaky, we could implement a simple service that stores/retrieves circuit strings for unique ids.

ariel-phet commented 8 years ago

@samreid - just circuit state, not other options need to be saved

samreid commented 8 years ago

In my testing of iPad, mac Chrome, mac Firefox and mac Safari, this is working well. On the latter 3 (but not on iPad), it also has good support for forward/back navigation.

samreid commented 7 years ago

It would be good to discuss the User Experience for how save load should work before I spend time on the UI. Some possibilities:

@arouinfar @ariel-phet @kathy-phet let's decide on this before I proceed.

samreid commented 7 years ago

Other considerations: how should we support save/load on iPad (if at all?) iPad has no file system. We could save circuits to local storage, but the save files wouldn't be transferrable to other computers. We could add a "share" button, which emails the circuit to the user, etc.

arouinfar commented 7 years ago

@samreid thanks for your suggestions. Here are my thoughts.

Save the state in query parameters. The user would create their circuit, then the URL would automatically update, then the user could bookmark the page. This could be confusing for users who just wanted to link to the blank CCK, not the circuit they created.

I think query parameters are probably the best option, but I'm not sure about automatically updating the URL is the way to go. As you've pointed out, there are some pretty obvious usability issues.

Add Save/Load buttons, that pop up a file save dialog where the user picks a place on their hard drive to save/load the file. This may be more conventional.

Is this a viable option for iPads? I think we want to find a solution that would work across all of our supported platforms.

Add a save button, and a "drop area" for loading. To load, the user would drag and drop a file into the play area and it would load.

Drop to load is interesting, and is already built into the browser. Dropping a .html file into Chrome, Firefox, or Safari will load the file in that tab. If a user saves a customized .html file, and then drags it into their browser window, the saved circuit will load.

@samreid In general, it sounds like using query parameters to create a customized URL is a viable option. I think one of the primary challenges will be delivering that URL to the user. I had a few thoughts about how we could save a customized URL. Both involve adding a "Save Circuit" option to the PhET Menu, though neither option is all that elegant.

image

image

arouinfar commented 7 years ago

I know we didn't get the chance to talk about this at design meeting, but perhaps we can have some of this discussion over GitHub. @samreid and/or @ariel-phet can you take a look at the suggestions in https://github.com/phetsims/circuit-construction-kit-common/issues/151#issuecomment-283515625? If you have any alternative suggestions, I'd be happy to mock them up before the next meeting.

samreid commented 7 years ago

Perhaps the most straightforward way (for our users and implementation) would be to use File Save (as we do for the "screenshot" button) and the File Load (as we do for the phet-io playback wrapper). This would not suffer from any limitation on file sizes and should be familiar with users. However, the user would need to be able to write files to their computer (may not be possible on all school computers).

ariel-phet commented 7 years ago

Guessing this is not something to shoot for for 1.0, removing assignment for the time being.

samreid commented 7 years ago

At today's meeting, we confirmed we want to save this for 1.1.

samreid commented 7 years ago

Here's some code I'm lifting out of CircuitConstructionKitScreenView until after 1.0

    // TODO: A better place to implement this?
    if ( CircuitConstructionKitQueryParameters.circuit ) {
      var circuitStateObject = JSON.parse( LZString.decompressFromEncodedURIComponent( CircuitConstructionKitQueryParameters.circuit ) );
      circuitConstructionKitModel.circuit.loadFromCircuitStruct( CircuitStruct.fromStateObject( circuitStateObject ) );
    }

    var enableSave = true;
    window.onpopstate = function( e ) {
      if ( e.state && e.state.circuit ) {
        var circuit = e.state.circuit;
        enableSave = false;
        console.log( 'loading from pop state' );
        circuitConstructionKitModel.circuit.loadFromCircuitStruct( CircuitStruct.fromStateObject( circuit ) );
        enableSave = true;
      }
    };

    var pushState = function() {
      if ( !enableSave ) {
        return;
      }
      console.log( 'push state' );
      var stateObject = circuitConstructionKitModel.circuit.toStateObject();
      var string = JSON.stringify( stateObject );
      var compressed = LZString.compressToEncodedURIComponent( string );
      console.log( string.length, ' => ', compressed.length );

      // assume circuit query parameter is last
      var text = window.location.href;
      if ( text.indexOf( '?circuit=' ) >= 0 ) {
        text = text.substring( 0, text.indexOf( '?circuit=' ) );
      }
      else if ( text.indexOf( '&circuit=' ) >= 0 ) {
        text = text.substring( 0, text.indexOf( '&circuit=' ) );
      }

      var join = text.indexOf( '?' ) >= 0 ? '&' : '?';

      window.history.pushState( { circuit: stateObject }, 'title', text + join + 'circuit=' + compressed );
    };

    if ( CircuitConstructionKitQueryParameters.showSaveButton ) {
      var saveButton = new TextPushButton( 'Save', {
        listener: pushState
      } );
      this.addChild( saveButton );
    }

// ...

      if ( CircuitConstructionKitQueryParameters.showSaveButton ) {
        saveButton.mutate( {
          right: visibleBounds.right - LAYOUT_INSET,
          bottom: resetAllButton.top - LAYOUT_INSET
        } );
      }
samreid commented 7 years ago

Save & Load will need to be screen-specific: some circuit elements are only available on screen 2.

oliver-phet commented 6 years ago

I recently got another user email about this feature. I noticed that iOS 11 has a Files app that might solve the questions above about iPad save?

samreid commented 4 years ago

As far as I know, this will not be part of the AC publication for Jan 31, 2020, deferring until afterwards.

oliver-phet commented 4 years ago

Another user email about this:

Is it possible to set up a simulation so that when students access it, they don't have to do all the building. I understand the point is student discovery, but I am giving them a picture of what I want them to build anyway. I am working with the Circuit Builder DC lab with 30 minute class sessions. What I would like to do is have a simple, series, and parallel circuit already made that students could use for an inquiry setup about the brightness current and voltage. They would then modify the circuits as they do the activity. With such a short class, I don't want them to have to spend 10-15 min just making the circuits.

samreid commented 3 years ago

Here is a posting to the Google Group from Jan 18, 2021:

Hi,

first let me express my gratitude to your work, I love your simulations and I use them regularly in my physics classes - now more than ever, of course!

There's just one feature I miss (or didn't find?), I'd like to be able to save a simulation state. E.g. I'd like to save a circuit in the above mentioned virtual lab, to present it to my class without having to set it up manually before class.

Furthermore, if the circuit could be saved in the URL's query string, it could be shared easily.

Best regards,

samreid commented 3 years ago

In a google groups thread, a user asked:

I've looked through the various postings and, while I cannot find any reference to saving PhET setups (say, a circuit with 4 particular resistors and a battery of a particular potential) for use as a quiz, I remember seeing a discussion on how there was no way to "save" a setup of a particular sim. Is this still true?

Rather than having my students follow a set of not-always-clear instructions on building a circuit and then asking questions for discovery, I'd like to be able to post or link to an already created circuit. Is this possible?

arouinfar commented 1 year ago

It may be possible to leverage the work done in #929 to add save/load functionality to the phet-brand sim.