[comp.sys.mac.hypercard] Copying contents of stacks

ns@CAT.CMU.EDU (Nicholas Spies) (03/10/88)

I want to copy the contents in fields of one stack to an updated version
new stack. I used a script like the one here...

on copyStuff -- executed from a button in the source stack
  put the number of cards into numCards
  repeat with i = 1 to numCards
    go card i of stack "sourceStack"
    put field "f1" into f1contents
    -- and so on
  
  go stack "destination" -- has one card to begin with, with fields, etc
  if i > the number of cards then
    doMenu "New Card"
  end if
 
  go card i

  put f1contents into field "f1" -- fields have same names
  -- and so on

 end repeat
end copyStuff

There are almost 1100 cards in the source stack. Of course I tried it a few
times on about 20 cards  to make sure things were working as expected, and
then let it go for about an hour to copy all field contents. I compacted the
destination stack only to find that only abour 5  card's worth of stuff had
been copied, even though all the cards were created in the destination
stack.

What gives? Did I unwittingly destroy all the imported information by
compacting the destination stack? Is there something that I have to do
to make sure the imported data sticks? Considering this didn't work, is there
a "right" way to do it?

Any suggestings would be appreciated...
-- 
Nicholas Spies			ns@cat.cmu.edu.arpa
Center for Design of Educational Computing
Carnegie Mellon University

beloin@batcomputer.tn.cornell.edu (Ron Beloin) (03/11/88)

In article <1080@PT.CS.CMU.EDU> ns@CAT.CMU.EDU (Nicholas Spies) writes:
>  put the number of cards into numCards
>  repeat with i = 1 to numCards
>    go card i of stack "sourceStack"
>    put field "f1" into f1contents
>    -- and so on
>  go stack "destination" -- has one card to begin with, with fields, etc
>  if i > the number of cards then
>    doMenu "New Card"


now, the new card is card number 2, since you started on card 1...

>  end if
> 
>  go card i 
this takes you to the last card, not the new one...

and this overwrites previous data...
So it had nothing to do with compacting the stack. I couldn't see what
was wrong until I played with it a bit. You can skip the if statement
above and just make a new card and stuff away..

ron
 Ron Beloin, Ecosystems Research Center, Corson Hall, Cornell, Ithaca,NY 14853
 >> opinions << BITNET:BELOIN@CRNLTHRY; INTERNET:beloin@tcgould.tn.cornell.edu
 >> are mine << UUCP:{cmcl2,shasta,uw-beaver,rochester}!cornell!tcgould!beloin

winkler@Apple.COM (Dan Winkler) (03/11/88)

Your script said:

  go stack "destination" 
  if i > the number of cards then
    doMenu "New Card"
  end if
  go card i
  put f1contents into field "f1" 

First of all, you don't need an "end if" with a single line if
statement, so you could have written:

  go stack "destination" 
  if i > the number of cards then doMenu "New Card"
  go card i
  put f1contents into field "f1" 

Or even:

  go stack "destination" 
  if i > the number of cards then doMenu "New Card"
  put f1contents into field "f1" of card i

Now, about your bug: your first go command takes you to the first card
of the destination stack.  The doMenu "New Card", if it's executed,
makes a new card right after the first one.  So the new card is card
number 2.  But you always write into card i, not on the new card you
created.  This can all be fixed by changing that first go so that it
reads:

  go to last card of stack "destination" 

So that when you make a new card it will be the very last card in the
stack.

edmoy@violet.berkeley.edu (03/11/88)

In article <1080@PT.CS.CMU.EDU> ns@CAT.CMU.EDU (Nicholas Spies) writes:
>I want to copy the contents in fields of one stack to an updated version
>new stack. I used a script like the one here...
>
>on copyStuff -- executed from a button in the source stack
>  put the number of cards into numCards
>  repeat with i = 1 to numCards
>    go card i of stack "sourceStack"
>    put field "f1" into f1contents
>    -- and so on
>  
>  go stack "destination" -- has one card to begin with, with fields, etc
>  if i > the number of cards then
>    doMenu "New Card"
>  end if
> 
>  go card i
>
>  put f1contents into field "f1" -- fields have same names
>  -- and so on
>
> end repeat
>end copyStuff
>
>There are almost 1100 cards in the source stack. Of course I tried it a few
>times on about 20 cards  to make sure things were working as expected, and
>then let it go for about an hour to copy all field contents. I compacted the
>destination stack only to find that only abour 5  card's worth of stuff had
>been copied, even though all the cards were created in the destination
>stack.
>
>What gives? Did I unwittingly destroy all the imported information by
>compacting the destination stack? Is there something that I have to do
>to make sure the imported data sticks? Considering this didn't work, is there
>a "right" way to do it?
>
>Any suggestings would be appreciated...
>-- 
>Nicholas Spies			ns@cat.cmu.edu.arpa
>Center for Design of Educational Computing
>Carnegie Mellon University

I think the problem is that when you do go stack "destination" and make the
new card, the card goes after the current card (the current card being the
first card when just entering the stack).  Then you go to the i'th card,
but that isn't the one you just created.

One way to fix the problem is to:

   go last card of stack "destination"
   if i > the number of cards then
      doMenu "New Card"
   end if
   put f1contents into field "f1"

I have a stack that is used by a group of consultants here at the computer
center.  I've had to update the stack ump-teen times so I had a similar
problem to yours.  I didn't want to have to go between stacks on each
card, because of the additional overhead of opening and closing stacks.
What I did was to write a text file having the information of the source
stack, then go to the destination stack and read the stuff back in.  The
code looked something like:

-- This is all from memory so if the syntax is a little off, forgive me

on dump
    open file "Temp File"
    put tab into fieldSeparator
    put return into cardSeparator
    go first card
    repeat with i = 1 to the number of cards
      get field "f1" && fieldSeparator && field "f2" && cardSeparator
      write it to file "Temp File"
      go next card
    end repeat
    close file "Temp File"
end dump

on restore
    open file "Temp File"
    put tab into fieldSeparator
    put return into cardSeparator
    read file "Temp File" until cardSeparator
    repeat until it is empty
      doMenu "New Card"
      put offset(fieldSeparator,it) into endOfRecord
      if endOfRecord > 1
      then put char 1 to (endOfRecord - 1) of it into field "f1"
      delete char 1 to endOfRecord of it
      put offset(fieldSeparator,it) into endOfRecord
      if endOfRecord > 1
      then put char 1 to (endOfRecord - 1) of it into field "f2"
      read file "Temp File" until cardSeparator
    end repeat
    close file "Temp File"
end restore

I would do "dump" in the source stack and then go to the destination stack
and do "restore".  In my stack, I had some 20 fields and it took about
6-8 seconds to write out each card and about 1-2 seconds to read it back
in.

I eventually wanted the intermediate output to be a way to transfer data
to Unix systems, where I have a simple program that can create and edit
the data which could be read into the stack.  This made it considerable
more complicated and (for some reason) writing it out took 2-4 seconds
and reading it back in took 6-10 seconds (it has to recognize various
key words, since the fields could come in any order).  This was much
too slow for what I had to do.  I finally wrote an XFCN that did the
same thing in C, and now it takes a second or less to write out a card,
and a second or two to read it back in.

Edward Moy
Workstation Software Support Group
University of California
Berkeley, CA  94720

edmoy@violet.Berkeley.EDU
ucbvax!violet!edmoy