From f6ea33c8bb18decb9236e9c2f56d62538adb823d Mon Sep 17 00:00:00 2001 From: TwokSSEi <63430518+TwokSSEi@users.noreply.github.com> Date: Sun, 7 Dec 2025 21:51:37 +0000 Subject: [PATCH] [Proposal ]Market Export Choice of Text Data format --- EDMC.py | 14 +++++++++++++- EDMarketConnector.py | 14 +++++++++++++- commodity.py | 35 +++++++++++++++++++++++++++-------- prefs.py | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 10 deletions(-) diff --git a/EDMC.py b/EDMC.py index 58264fb0..67c1d818 100755 --- a/EDMC.py +++ b/EDMC.py @@ -402,7 +402,19 @@ def main() -> None: # noqa: C901, CCR001 if data['lastStarport'].get('commodities'): # Fixup anomalies in the commodity data fixed = companion.fixup(data) - commodity.export(fixed, COMMODITY_DEFAULT, args.m) + # Determine user-selected market export type (CSV, TAB, PIPE, SEMICOLON) + mkt_type = config.get_str('mkt_export_type', default='SEMICOLON') + if mkt_type == 'CSV': + kind = commodity.COMMODITY_CSV + elif mkt_type == 'CSV_NEW': + kind = commodity.COMMODITY_CSV_NEW + elif mkt_type == 'TAB': + kind = commodity.COMMODITY_TAB + elif mkt_type == 'PIPE': + kind = commodity.COMMODITY_PIPE + else: + kind = commodity.COMMODITY_SEMICOLON + commodity.export(fixed, kind, args.m) else: logger.error("Station doesn't have a market") diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 587cdf73..0d1084b1 100644 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -987,7 +987,19 @@ class AppWindow: # Fixup anomalies in the comodity data fixed = companion.fixup(data) if output_flags & config.OUT_MKT_CSV: - commodity.export(fixed, COMMODITY_CSV) + # Determine user-selected market export type (CSV, TAB, PIPE, SEMICOLON) + mkt_type = config.get_str('mkt_export_type', default='SEMICOLON') + if mkt_type == 'CSV': + kind = commodity.COMMODITY_CSV + elif mkt_type == 'CSV_NEW': + kind = commodity.COMMODITY_CSV_NEW + elif mkt_type == 'TAB': + kind = commodity.COMMODITY_TAB + elif mkt_type == 'PIPE': + kind = commodity.COMMODITY_PIPE + else: + kind = commodity.COMMODITY_SEMICOLON + commodity.export(fixed, kind) if output_flags & config.OUT_MKT_TD: td.export(fixed) diff --git a/commodity.py b/commodity.py index 52c13928..70cd6167 100644 --- a/commodity.py +++ b/commodity.py @@ -10,7 +10,15 @@ from edmc_data import commodity_bracketmap as bracketmap # DEFAULT means semi-colon separation # CSV means comma separation -(COMMODITY_DEFAULT, COMMODITY_CSV) = range(2) +# TAB and PIPE are also supported +( + COMMODITY_SEMICOLON, + COMMODITY_CSV, + COMMODITY_CSV_NEW, + COMMODITY_TAB, + COMMODITY_PIPE, +) = range(5) +mkt_out_types = ('CSV', 'CSV_NEW', 'TAB', 'PIPE', 'SEMICOLON') def export(data, kind=COMMODITY_DEFAULT, filename=None) -> None: # noqa: CCR001 @@ -24,11 +32,22 @@ def export(data, kind=COMMODITY_DEFAULT, filename=None) -> None: # noqa: CCR001 """ querytime = config.get_int("querytime", default=int(time.time())) + # Map kind to delimiter + if kind == COMMODITY_CSV or kind == COMMODITY_CSV_NEW: + mkt_out_delim = ',' + elif kind == COMMODITY_TAB: + mkt_out_delim = '\t' + elif kind == COMMODITY_PIPE: + mkt_out_delim = '|' + else: + mkt_out_delim = ';' # COMMODITY_SEMICOLON or default + if not filename: sysname = data["lastSystem"]["name"].strip() station = data["lastStarport"]["name"].strip() timestamp = time.strftime("%Y-%m-%dT%H.%M.%S", time.localtime(querytime)) - ext = "csv" if kind == COMMODITY_CSV else "scsv" + # Use .csv for comma-separated files; use .txt for other text formats + ext = 'csv' if mkt_out_delim == ',' else 'txt' filename = ( Path(config.get_str("outdir")) / f"{sysname}.{station}.{timestamp}.{ext}" ) @@ -37,14 +56,13 @@ def export(data, kind=COMMODITY_DEFAULT, filename=None) -> None: # noqa: CCR001 station = data["lastStarport"]["name"] if kind == COMMODITY_CSV: - header = ["System", "Station", "Commodity", "Sell", "Buy", "Demand", - "", "Supply", "", "Date"] + # maintain old compatibility + header = ['System', 'Station', 'Commodity', 'Sell', 'Buy', 'Demand', 'demandBracket', 'Supply', 'stockBracket', 'Date'] else: - header = ["System", "Station", "Commodity", "Sell", "Buy", "Demand", - "", "Supply", "", "Average", "FDevID", "Date"] + header = ['System', 'Station', 'Commodity', 'Sell', 'Buy', 'Demand', 'demandBracket', 'Supply', 'stockBracket', 'Average', 'FDevID', 'Date'] with open(filename, "w", newline="", encoding="utf-8") as output_file: - writer = csv.writer(output_file, delimiter=";" if kind == COMMODITY_DEFAULT else ",") + writer = csv.writer(output_file, delimiter=mkt_out_delim) writer.writerow(header) @@ -61,7 +79,8 @@ def export(data, kind=COMMODITY_DEFAULT, filename=None) -> None: # noqa: CCR001 bracketmap.get(commodity.get("stockBracket"), ""), ] - if kind == COMMODITY_DEFAULT: + # newer export fields format + if kind != COMMODITY_CSV: mean = int(commodity["meanPrice"]) if commodity.get("meanPrice") is not None else "" row.extend([mean, commodity["id"]]) diff --git a/prefs.py b/prefs.py index 9b82704a..c4607324 100644 --- a/prefs.py +++ b/prefs.py @@ -25,6 +25,7 @@ from monitor import monitor from theme import theme from ttkHyperlinkLabel import HyperlinkLabel from common_utils import ensure_on_screen +import commodity logger = get_main_logger() @@ -354,6 +355,34 @@ class PreferencesDialog(tk.Toplevel): ) self.out_csv_button.grid(columnspan=2, padx=self.BUTTONX, pady=self.PADY, sticky=tk.W, row=row.get()) + # Export format selection for market text exports + # LANG: Settings > Output - choose delimiter/format for market export files + # Group the Label and the ComboBox for consistent layout reflow + mkt_frame = nb.Frame(output_frame) #, borderwidth=1, relief=tk.SOLID) + mkt_frame.grid(padx=self.PADX, pady=self.PADY, sticky=tk.EW, row=row.get()) # add increment row for the sub-frame + + self.mkt_export_type = tk.StringVar() + # Default to SEMICOLON for backward compatibility; normalise any saved value + _mkt_saved = config.get_str('mkt_export_type', default='SEMICOLON') or 'SEMICOLON' + _mkt_saved = _mkt_saved.upper() + if _mkt_saved not in commodity.mkt_out_types: # ('CSV', 'CSV_NEW', 'TAB', 'PIPE', 'SEMICOLON'): + _mkt_saved = 'SEMICOLON' + self.mkt_export_type.set(_mkt_saved) + + nb.Label(mkt_frame, text=tr.tl(' Market export format') + ': ').grid( + padx=self.PADX, pady=self.PADY, sticky=tk.W, column=0, row=0 + ) + # Use a read-only combobox to present options + self.mkt_export_combobox = ttk.Combobox( + mkt_frame, + textvariable=self.mkt_export_type, + values=commodity.mkt_out_types, + state='readonly', + width=12 + ) + # self.mkt_export_combobox.grid(column=2, padx=self.PADX, pady=self.BOXY, sticky=tk.W, row=row.get()) + self.mkt_export_combobox.grid(padx=self.PADX, pady=self.PADY, sticky=tk.W, column=1, row=0) + self.out_td = tk.IntVar(value=1 if (output & config.OUT_MKT_TD) else 0) self.out_td_button = nb.Checkbutton( output_frame, @@ -1311,6 +1340,12 @@ class PreferencesDialog(tk.Toplevel): )) ) + # Market export format selected by user: one of CSV, TAB, PIPE, SEMICOLON + _val = (self.mkt_export_type.get() or '').upper() + if _val not in commodity.mkt_out_types: + _val = 'SEMICOLON' + config.set('mkt_export_type', _val) + config.set( 'outdir', join(config.home_path, self.outdir.get()[2:]) if self.outdir.get().startswith('~') else self.outdir.get()