Core SuperMemo XML for exchange of text questions, answers and learning data

This is a simplified core implementation for basic data exchange between SuperMemo for Windows, SuperMemo for Pocket PC, SuperMemo for Palm Pilot, On-line SuperMemo, SuperMemo Library, and other platforms currently in development.

Here is an intuitive example (actual files exported by SuperMemo for Windows can be found here):

<?xml version="1.0" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="http://supermemo.com/archive/beta/tmp/xml/supermemo.xsl"?>
<SuperMemoCollection>
  <Count>1329</Count>
  <SuperMemoElement>
      <ID>78345</ID>
      <Content>
         <Question>hist: The city of Carthage, located in what is now Tunisia, had been founded in [...] by the Phoenicians</Question>
         <Answer>814 BC</Answer>
  
    </Content>
    <LearningData>
       <Interval>323</Interval>
       <Repetitions>3</Repetitions>
       <Lapses>1</Lapses> 
       <LastRepetition>23.11.2000</LastRepetition>
       <AFactor>1.456</AFactor> 
       <UFactor>1.121</UFactor>
    </LearningData>
             <SuperMemoElement>
             
      <ID>78346</ID>
                          <Content>
                               ...
                          </Content>
             </SuperMemoElement>
  </SuperMemoElement>
</SuperMemoCollection>


Procedures

Heuristic conversion of E-Factors to A-Factors (subject to change):

const
minAF=1.2;
maxAF=6.9;
minEF=1.3;
maxEF=3.3;

function EFactor2AFactor(EF:real):real;
begin
  Result:=minAF+(EF-minEF)/(maxEF-minEF)*(maxAF-minAF);
  if Result>maxAF then Result:=maxAF;
  if Result<minAF then Result:=minAF;
end;

function AFactor2EFactor(AF:real):real;
begin
  Result:=minEF+(AF-minAF)/(maxAF-minAF)*(maxEF-minEF);
  if Result>maxEF then Result:=maxEF;
  if Result<minEF then Result:=minEF;
end;

function EFactor2UFactor(EF:real;Repetitions:byte):real;
begin
  if Repetitions=1 then 
     Result:=1 
  else 
     Result:=EF;
end;

Extended HTML encoding for embedding Unicode in XML:

function HTMLEncode(WS:WideString):string; 
var n:integer; ch:WideChar; w:word; s:string;
begin 
  Result:='';
  for n:=1 to length(WS) do begin
       ch:=WS[n];
       w:=word(ch);
       if w>127 then begin 
          s:=IntToStr(w);
          s:='&#'+s+';';
          end
       else s:=ch;
   Result:=Result+s;
   end;
end;