Task 613: .RKT File Format
Task 613: .RKT File Format
1. List of all the properties of the .RKT file format intrinsic to its file system
Based on analysis of the RockSim .RKT file format (which is an XML-based structure for rocket design and simulation data), the key properties are derived from its XML elements and hierarchy. These are intrinsic to the format itself and include metadata, design components, and simulation data. The format is ASCII XML, self-documenting, and divided into main sections for design and simulations. Here's the comprehensive list:
- File Version: The version of the RockSim file format (e.g., under ).
- Rocket Summary/Design Information: Includes rocket name, designer, revision history, comments, and overall summary (e.g., under ).
- Rocket Design Structure: The physical design of the rocket, independent of motors or simulations (e.g., under ).
- Stages: Breakdown by stages (e.g., for a typical single-stage or multi-stage setup, with sub-elements for additional stages if present).
- Parts and Components: Detailed specifications for each part in the rocket design.
- Nose cone: Shape, length, diameter, material, thickness, position.
- Body tubes: Length, inner/outer diameter, material, thickness, position.
- Transitions: Shape, length, fore/aft diameters, material, thickness, position.
- Fins: Shape (e.g., trapezoid, ellipse), root chord, tip chord, height, sweep, thickness, material, count, position, fillet details.
- Bulkheads/Centering rings: Diameter, thickness, material, position.
- Parachutes/Streamers: Diameter/length, material, shroud line details, spill hole, deployment settings.
- Mass objects: Mass, position, description.
- Engine mounts/Tubes: Length, diameter, position, overhang.
- Launch lugs/Buttons: Length, diameter, position, count.
- Other internal components: Shock cords, attachments, etc.
- Materials and Finishes: Material types (e.g., balsa, cardboard), density, finish (e.g., painted, roughness).
- Mass and Stability Properties: Calculated or overridden mass, center of gravity (CG), center of pressure (CP), moments of inertia.
- Simulation Results List: An array of simulation data (e.g., under , with each representing one simulation).
- Simulation Metadata: Simulation name, number (zero-based index), description.
- Input Parameters: Motor type/configuration, launch rod length/angle, wind speed, temperature, pressure, altitude, latitude.
- Output Results: Max altitude, max velocity, max acceleration, deployment altitude, time to apogee, ground hit velocity, flight time, data points (time, altitude, velocity arrays).
- Events: Ignition, burnout, ejection, deployment events with timings.
These properties are extracted from the XML hierarchy, starting from the root .
2. Two direct download links for files of format .RKT
- https://www.rocketreviews.com/file-27459/rocketman_praying_mantis_stock.rkt
- https://www.rocketreviews.com/file-168857/SLS Scale 100 experimental.rkt
3. Ghost blog embedded HTML JavaScript for drag-n-drop .RKT file dump
Here's the complete HTML with embedded JavaScript. It allows dragging and dropping a .RKT file, parses it as XML, and dumps all properties (tags, attributes, and text values) to the screen in a hierarchical list.
Drag and Drop .RKT File
4. Python class for .RKT file handling
import xml.etree.ElementTree as ET
import os
class RKTFileHandler:
def __init__(self, filename):
self.filename = filename
self.tree = None
self.root = None
def open_and_decode(self):
if not os.path.exists(self.filename):
raise FileNotFoundError(f"File {self.filename} not found.")
self.tree = ET.parse(self.filename)
self.root = self.tree.getroot()
def read_properties(self):
if self.root is None:
raise ValueError("File not opened or decoded.")
properties = {}
# Extract key sections
properties['FileVersion'] = self.root.find('FileVersion').text if self.root.find('FileVersion') else 'Unknown'
design_info = self.root.find('DesignInformation')
if design_info:
properties['DesignInformation'] = {child.tag: child.text for child in design_info}
rocket_design = self.root.find('RocketDesign')
if rocket_design:
properties['RocketDesign'] = self._extract_parts(rocket_design)
sim_list = self.root.find('SimulationResultsList')
if sim_list:
properties['SimulationResultsList'] = []
for sim in sim_list.findall('SimulationResult'):
sim_data = {child.tag: child.text for child in sim}
properties['SimulationResultsList'].append(sim_data)
return properties
def _extract_parts(self, node):
parts = {}
for child in node:
if child.tag not in parts:
parts[child.tag] = []
part_data = {'attributes': dict(child.attrib), 'text': child.text}
for subchild in child:
part_data[subchild.tag] = subchild.text
parts[child.tag].append(part_data)
return parts
def print_properties(self):
props = self.read_properties()
print("RKT Properties:")
for key, value in props.items():
print(f"{key}: {value}")
def write(self, new_filename=None):
if self.tree is None:
raise ValueError("No data to write.")
filename = new_filename or self.filename
self.tree.write(filename, encoding='utf-8', xml_declaration=True)
# Example usage:
# handler = RKTFileHandler('example.rkt')
# handler.open_and_decode()
# handler.print_properties()
# handler.write('modified.rkt')
5. Java class for .RKT file handling
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
public class RKTFileHandler {
private String filename;
private Document doc;
public RKTFileHandler(String filename) {
this.filename = filename;
}
public void openAndDecode() throws Exception {
File file = new File(filename);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
this.doc = dBuilder.parse(file);
this.doc.getDocumentElement().normalize();
}
public Map<String, Object> readProperties() {
if (doc == null) {
throw new IllegalStateException("File not opened or decoded.");
}
Map<String, Object> properties = new HashMap<>();
Element root = doc.getDocumentElement();
// File Version
Node versionNode = root.getElementsByTagName("FileVersion").item(0);
properties.put("FileVersion", versionNode != null ? versionNode.getTextContent() : "Unknown");
// Design Information
Node designInfo = root.getElementsByTagName("DesignInformation").item(0);
if (designInfo != null) {
properties.put("DesignInformation", extractChildMap((Element) designInfo));
}
// Rocket Design
Node rocketDesign = root.getElementsByTagName("RocketDesign").item(0);
if (rocketDesign != null) {
properties.put("RocketDesign", extractParts((Element) rocketDesign));
}
// Simulation Results List
Node simList = root.getElementsByTagName("SimulationResultsList").item(0);
if (simList != null) {
List<Map<String, String>> sims = new ArrayList<>();
NodeList simNodes = ((Element) simList).getElementsByTagName("SimulationResult");
for (int i = 0; i < simNodes.getLength(); i++) {
sims.add(extractChildMap((Element) simNodes.item(i)));
}
properties.put("SimulationResultsList", sims);
}
return properties;
}
private Map<String, String> extractChildMap(Element element) {
Map<String, String> map = new HashMap<>();
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
map.put(child.getNodeName(), child.getTextContent());
}
}
return map;
}
private Map<String, List<Map<String, Object>>> extractParts(Element node) {
Map<String, List<Map<String, Object>>> parts = new HashMap<>();
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
Element el = (Element) child;
String tag = el.getTagName();
parts.computeIfAbsent(tag, k -> new ArrayList<>());
Map<String, Object> partData = new HashMap<>();
for (int j = 0; j < el.getAttributes().getLength(); j++) {
Node attr = el.getAttributes().item(j);
partData.put(attr.getNodeName(), attr.getNodeValue());
}
partData.put("text", el.getTextContent());
NodeList subChildren = el.getChildNodes();
for (int k = 0; k < subChildren.getLength(); k++) {
Node sub = subChildren.item(k);
if (sub.getNodeType() == Node.ELEMENT_NODE) {
partData.put(sub.getNodeName(), sub.getTextContent());
}
}
parts.get(tag).add(partData);
}
}
return parts;
}
public void printProperties() {
try {
Map<String, Object> props = readProperties();
System.out.println("RKT Properties:");
props.forEach((key, value) -> System.out.println(key + ": " + value));
} catch (Exception e) {
e.printStackTrace();
}
}
public void write(String newFilename) throws Exception {
if (doc == null) {
throw new IllegalStateException("No data to write.");
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(newFilename != null ? newFilename : filename));
transformer.transform(source, result);
}
// Example usage:
// public static void main(String[] args) throws Exception {
// RKTFileHandler handler = new RKTFileHandler("example.rkt");
// handler.openAndDecode();
// handler.printProperties();
// handler.write("modified.rkt");
// }
}
6. JavaScript class for .RKT file handling
class RKTFileHandler {
constructor(filename) {
this.filename = filename;
this.xmlDoc = null;
}
async openAndDecode() {
const response = await fetch(this.filename);
if (!response.ok) {
throw new Error(`File ${this.filename} not found.`);
}
const xmlText = await response.text();
const parser = new DOMParser();
this.xmlDoc = parser.parseFromString(xmlText, 'application/xml');
if (this.xmlDoc.getElementsByTagName('parsererror').length > 0) {
throw new Error('Error parsing XML.');
}
}
readProperties() {
if (!this.xmlDoc) {
throw new Error('File not opened or decoded.');
}
const properties = {};
const root = this.xmlDoc.documentElement;
// File Version
const version = root.querySelector('FileVersion');
properties.FileVersion = version ? version.textContent : 'Unknown';
// Design Information
const designInfo = root.querySelector('DesignInformation');
if (designInfo) {
properties.DesignInformation = this._extractChildMap(designInfo);
}
// Rocket Design
const rocketDesign = root.querySelector('RocketDesign');
if (rocketDesign) {
properties.RocketDesign = this._extractParts(rocketDesign);
}
// Simulation Results List
const simList = root.querySelector('SimulationResultsList');
if (simList) {
properties.SimulationResultsList = [];
const sims = simList.querySelectorAll('SimulationResult');
sims.forEach(sim => {
properties.SimulationResultsList.push(this._extractChildMap(sim));
});
}
return properties;
}
_extractChildMap(element) {
const map = {};
element.childNodes.forEach(child => {
if (child.nodeType === Node.ELEMENT_NODE) {
map[child.tagName] = child.textContent;
}
});
return map;
}
_extractParts(node) {
const parts = {};
node.childNodes.forEach(child => {
if (child.nodeType === Node.ELEMENT_NODE) {
const tag = child.tagName;
if (!parts[tag]) parts[tag] = [];
const partData = { attributes: {}, text: child.textContent };
for (let attr of child.attributes) {
partData.attributes[attr.name] = attr.value;
}
child.childNodes.forEach(sub => {
if (sub.nodeType === Node.ELEMENT_NODE) {
partData[sub.tagName] = sub.textContent;
}
});
parts[tag].push(partData);
}
});
return parts;
}
printProperties() {
const props = this.readProperties();
console.log('RKT Properties:');
console.dir(props);
}
write(newFilename) {
if (!this.xmlDoc) {
throw new Error('No data to write.');
}
const serializer = new XMLSerializer();
const xmlStr = serializer.serializeToString(this.xmlDoc);
// For browser, this could download; for Node.js, use fs.writeFile
console.log('Writing to console (simulate write):', xmlStr);
// To actually write in Node.js: require('fs').writeFileSync(newFilename || this.filename, xmlStr);
}
}
// Example usage (in browser or Node with fetch polyfill):
// const handler = new RKTFileHandler('example.rkt');
// await handler.openAndDecode();
// handler.printProperties();
// handler.write('modified.rkt');
7. C class for .RKT file handling
Note: C does not have built-in XML parsing like higher-level languages. This implementation assumes use of a simple XML library like Mini-XML (mxml.h), which is lightweight and common for such tasks. If no library is allowed, a full custom parser would be too complex for this scope; assume mxml is available or replace with your preferred lib. The class is written in C++ for object-oriented style (as "c class" likely implies C++).
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <mxml.h> // Assume Mini-XML library for parsing
class RKTFileHandler {
private:
std::string filename;
mxml_node_t* tree;
mxml_node_t* root;
public:
RKTFileHandler(const std::string& fn) : filename(fn), tree(nullptr), root(nullptr) {}
~RKTFileHandler() {
if (tree) mxmlDelete(tree);
}
void openAndDecode() {
FILE* fp = fopen(filename.c_str(), "r");
if (!fp) {
throw std::runtime_error("File not found.");
}
tree = mxmlLoadFile(fp, MXML_TEXT_CALLBACK);
fclose(fp);
if (!tree) {
throw std::runtime_error("Error parsing XML.");
}
root = mxmlFindElement(tree, tree, "RockSimDocument", NULL, NULL, MXML_DESCEND);
if (!root) {
throw std::runtime_error("Invalid RKT file.");
}
}
std::map<std::string, std::any> readProperties() {
if (!root) {
throw std::runtime_error("File not opened or decoded.");
}
std::map<std::string, std::any> properties;
// File Version
mxml_node_t* version = mxmlFindElement(root, root, "FileVersion", NULL, NULL, MXML_DESCEND_FIRST);
properties["FileVersion"] = version ? std::string(mxmlGetText(version, NULL)) : std::string("Unknown");
// Design Information
mxml_node_t* designInfo = mxmlFindElement(root, root, "DesignInformation", NULL, NULL, MXML_DESCEND_FIRST);
if (designInfo) {
properties["DesignInformation"] = extractChildMap(designInfo);
}
// Rocket Design
mxml_node_t* rocketDesign = mxmlFindElement(root, root, "RocketDesign", NULL, NULL, MXML_DESCEND_FIRST);
if (rocketDesign) {
properties["RocketDesign"] = extractParts(rocketDesign);
}
// Simulation Results List
mxml_node_t* simList = mxmlFindElement(root, root, "SimulationResultsList", NULL, NULL, MXML_DESCEND_FIRST);
if (simList) {
std::vector<std::map<std::string, std::string>> sims;
mxml_node_t* sim = mxmlFindElement(simList, simList, "SimulationResult", NULL, NULL, MXML_DESCEND);
while (sim) {
sims.push_back(extractChildMap(sim));
sim = mxmlFindElement(sim, simList, "SimulationResult", NULL, NULL, MXML_NO_DESCEND);
}
properties["SimulationResultsList"] = sims;
}
return properties;
}
std::map<std::string, std::string> extractChildMap(mxml_node_t* node) {
std::map<std::string, std::string> map;
mxml_node_t* child = mxmlGetFirstChild(node);
while (child) {
if (mxmlGetType(child) == MXML_ELEMENT) {
map[mxmlGetElement(child)] = std::string(mxmlGetText(child, NULL));
}
child = mxmlGetNextSibling(child);
}
return map;
}
std::map<std::string, std::vector<std::map<std::string, std::any>>> extractParts(mxml_node_t* node) {
std::map<std::string, std::vector<std::map<std::string, std::any>>> parts;
mxml_node_t* child = mxmlGetFirstChild(node);
while (child) {
if (mxmlGetType(child) == MXML_ELEMENT) {
std::string tag = mxmlGetElement(child);
std::map<std::string, std::any> partData;
// Attributes (Mini-XML attr access)
const char* attr_name;
for (int i = 0; (attr_name = mxmlElementGetAttrByIndex(child, i, NULL)); ++i) {
partData[attr_name] = std::string(mxmlElementGetAttr(child, attr_name));
}
partData["text"] = std::string(mxmlGetText(child, NULL));
// Subchildren
mxml_node_t* sub = mxmlGetFirstChild(child);
while (sub) {
if (mxmlGetType(sub) == MXML_ELEMENT) {
partData[mxmlGetElement(sub)] = std::string(mxmlGetText(sub, NULL));
}
sub = mxmlGetNextSibling(sub);
}
parts[tag].push_back(partData);
}
child = mxmlGetNextSibling(child);
}
return parts;
}
void printProperties() {
auto props = readProperties();
std::cout << "RKT Properties:" << std::endl;
// Printing is simplified; use recursion or loops for nested maps
for (const auto& [key, value] : props) {
std::cout << key << ": [complex value]" << std::endl; // Expand as needed
}
}
void write(const std::string& newFilename = "") {
if (!tree) {
throw std::runtime_error("No data to write.");
}
std::string outFile = newFilename.empty() ? filename : newFilename;
FILE* fp = fopen(outFile.c_str(), "w");
if (!fp) {
throw std::runtime_error("Cannot write file.");
}
mxmlSaveFile(tree, fp, MXML_NO_CALLBACK);
fclose(fp);
}
};
// Example usage:
// int main() {
// try {
// RKTFileHandler handler("example.rkt");
// handler.openAndDecode();
// handler.printProperties();
// handler.write("modified.rkt");
// } catch (const std::exception& e) {
// std::cerr << e.what() << std::endl;
// }
// return 0;
// }