#include <stdio.h>
#include <string.h>

//相位偏移子结构体
typedef struct{
    char sys;
    char obs_code[4];
    double shift;
}PhsItem;

//单星座观测配置
typedef struct{
    char sys;
    int obs_cnt;
    char obs_str[130];
}SysObsItem;

//GLO卫星频点
typedef struct{
    char sat[4];
    int fn;
}GloFrqItem;

//整体RINEX头部总结构体
typedef struct{
    //1版本软件
    char ver[10];
    char prog[22];
    char tool[22];
    char create_time[30];

    //2测站基础
    char mark_name[32];
    char mark_no[16];
    char mark_type[64];
    char observer[64];
    char agency[64];

    //3接收机天线
    char rcv_sn[22];
    char rcv_mod[22];
    char rcv_ver[22];
    char ant_sn[22];
    char ant_mod[22];

    //4坐标XYZ、天线H/E/N
    double XYZ[3];
    double HEN[3];

    //5各星座观测配置 G/R/C/S/J/E
    SysObsItem obs_list[6];
    char sig_unit[10];

    //6时间采样
    double interval;
    int t_start_y,t_start_m,t_start_d,t_start_h,t_start_mi;
    double t_start_sec;
    int t_end_y,t_end_m,t_end_d,t_end_h,t_end_mi;
    double t_end_sec;
    char time_sys[5];
    int rcv_clk_app;

    //7相位偏移
    PhsItem phs_arr[30];
    int phs_num;

    //8 GLO配置
    int glo_cnt;
    GloFrqItem glo_list[30];
    double glo_bias[3];

    //9跳秒
    int leap_sec;

    //10自定义注释行
    char comm[5][80];
    int comm_cnt;
}RinexHead;

//生成RINEX头部写入文件
void write_rinex_header(FILE *fp,RinexHead *hd)
{
    int i,j,idx;
    //1版本行
    fprintf(fp,"%9sOBSERVATION DATA    M (MIXED)           RINEX VERSION / TYPE\n",hd->ver);
    //软件时间
    fprintf(fp,"%-20s%-20s%s PGM / RUN BY / DATE \n",hd->prog,hd->tool,hd->create_time);
    //固定星座注释两行
    fprintf(fp,"       G = GPS       R = GLONASS       C = COMPASS          COMMENT             \n");
    fprintf(fp,"       S = SBAS      J = QZSS          E = GALILEO          COMMENT             \n");
    //点名编号类型
    fprintf(fp,"%-52sMARKER NAME         \n",hd->mark_name);
    fprintf(fp,"%-52sMARKER NUMBER      \n",hd->mark_no);
    fprintf(fp,"%-52sMARKER TYPE       \n",hd->mark_type);
    fprintf(fp,"%-52sOBSERVER / AGENCY \n",hd->observer);
    //接收机
    fprintf(fp,"%-20s%-20s%s     REC # / TYPE / VERS \n",hd->rcv_sn,hd->rcv_mod,hd->rcv_ver);
    //天线
    fprintf(fp,"%-20s%s                                  ANT # / TYPE        \n",hd->ant_sn,hd->ant_mod);
    //XYZ
    fprintf(fp,"%14.4f%16.4f%16.4f                  APPROX POSITION XYZ \n",hd->XYZ[0],hd->XYZ[1],hd->XYZ[2]);
    //HEN
    fprintf(fp,"%12.4f%12.4f%12.4f                  ANTENNA: DELTA H/E/N\n",hd->HEN[0],hd->HEN[1],hd->HEN[2]);
    //各星座观测
    for(i=0;i<6;i++){
        fprintf(fp,"%c%4d %-60sSYS / # / OBS TYPES \n",
            hd->obs_list[i].sys,hd->obs_list[i].obs_cnt,hd->obs_list[i].obs_str);
    }
    //信噪比单位
    fprintf(fp,"%-52sSIGNAL STRENGTH UNIT\n",hd->sig_unit);
    //采样间隔
    fprintf(fp,"%10.3f                                                  INTERVAL            \n",hd->interval);
    //起始结束时间
    fprintf(fp,"%6d%5d%5d%5d%5d%11.7f     %s         TIME OF FIRST OBS   \n",
        hd->t_start_y,hd->t_start_m,hd->t_start_d,hd->t_start_h,hd->t_start_mi,hd->t_start_sec,hd->time_sys);
    fprintf(fp,"%6d%5d%5d%5d%5d%11.7f     %s         TIME OF LAST OBS    \n",
        hd->t_end_y,hd->t_end_m,hd->t_end_d,hd->t_end_h,hd->t_end_mi,hd->t_end_sec,hd->time_sys);
    //钟差标志
    fprintf(fp,"%6d                                                      RCV CLOCK OFFS APPL \n",hd->rcv_clk_app);
    //相位偏移
    for(i=0;i<hd->phs_num;i++){
        fprintf(fp,"%c %-4s%8.5f                                              SYS / PHASE SHIFT \n",
            hd->phs_arr[i].sys,hd->phs_arr[i].obs_code,hd->phs_arr[i].shift);
    }
    //GLO频点 一行最多8个
    idx=0;
    while(idx < hd->glo_cnt){
        char tmpbuf[128]={0};
        int pos=0;
        for(j=0;j<8 && idx<hd->glo_cnt;j++){
            pos += sprintf(tmpbuf+pos,"%s %d ",hd->glo_list[idx].sat,hd->glo_list[idx].fn);
            idx++;
        }
        fprintf(fp,"%sGLONASS SLOT / FRQ #\n",tmpbuf);
    }
    //GLO码偏
    fprintf(fp,"C1C   %7.3f C2C   %7.3f C2P   %7.3f                     GLONASS COD/PHS/BIS \n",
        hd->glo_bias[0],hd->glo_bias[1],hd->glo_bias[2]);
    //跳秒
    fprintf(fp,"%6d                                                      LEAP SECONDS        \n",hd->leap_sec);
    //自定义注释
    for(i=0;i<hd->comm_cnt;i++){
        fprintf(fp,"%-52sCOMMENT\n",hd->comm[i]);
    }
    //结束
    fprintf(fp,"                                                            END OF HEADER\n");
}

int main(void)
{
    FILE *fp = fopen("out.obs","w");
    if(!fp) return -1;
    RinexHead hd={0};

    //====填入示例参数====
    strcpy(hd.ver,"3.02");
    strcpy(hd.prog,"Assistant 1.0");
    strcpy(hd.tool,"StaticToRinex");
    strcpy(hd.create_time,"20250516 213116 LCL");

    strcpy(hd.mark_name,"st1128");
    strcpy(hd.mark_no,"1");
    strcpy(hd.observer,"");
    strcpy(hd.agency,"");

    strcpy(hd.rcv_sn,"GS1051811016");
    strcpy(hd.rcv_mod,"G50");
    strcpy(hd.rcv_ver,"2e21c-202411280");
    strcpy(hd.ant_sn,"0");
    strcpy(hd.ant_mod,"TGAG50");

    hd.XYZ[0]=-2329499.4793;
    hd.XYZ[1]=4563766.0665;
    hd.XYZ[2]=3785618.2467;
    hd.HEN[0]=1.8530;
    hd.HEN[1]=0.0;
    hd.HEN[2]=0.0;

    //逐个赋值观测
    hd.obs_list[0].sys='G';
    hd.obs_list[0].obs_cnt=12;
    strcpy(hd.obs_list[0].obs_str,"C1C L1C D1C S1C C2Y L2Y D2Y S2Y C5Q L5Q D5Q S5Q");

    hd.obs_list[1].sys='R';
    hd.obs_list[1].obs_cnt=8;
    strcpy(hd.obs_list[1].obs_str,"C1C L1C D1C S1C C2P L2P D2P S2P");

    hd.obs_list[2].sys='C';
    hd.obs_list[2].obs_cnt=12;
    strcpy(hd.obs_list[2].obs_str,"C1I L1I D1I S1I C7I L7I D7I S7I C6I L6I D6I S6I");

    hd.obs_list[3].sys='S';
    hd.obs_list[3].obs_cnt=4;
    strcpy(hd.obs_list[3].obs_str,"C1C L1C D1C S1C");

    hd.obs_list[4].sys='J';
    hd.obs_list[4].obs_cnt=12;
    strcpy(hd.obs_list[4].obs_str,"C1C L1C D1C S1C C2S L2S D2S S2S C5Q L5Q D5Q S5Q");

    hd.obs_list[5].sys='E';
    hd.obs_list[5].obs_cnt=12;
    strcpy(hd.obs_list[5].obs_str,"C1C L1C D1C S1C C5Q L5Q D5Q S5Q C7Q L7Q D7Q S7Q");

    strcpy(hd.sig_unit,"DBHZ");

    hd.interval=15.0;
    //起始时间
    hd.t_start_y=2025;hd.t_start_m=5;hd.t_start_d=14;hd.t_start_h=0;hd.t_start_mi=56;hd.t_start_sec=30.0;
    hd.t_end_y=2025;hd.t_end_m=5;hd.t_end_d=14;hd.t_end_h=2;hd.t_end_mi=38;hd.t_end_sec=30.0;
    strcpy(hd.time_sys,"GPS");
    hd.rcv_clk_app=0;

    //相位偏移列表
    PhsItem plist[]={
        {'G',"L1C",0.00000},{'G',"L2Y",0.00000},{'G',"L5Q",-0.25000},
        {'R',"L1C",0.00000},{'R',"L2P",0.25000},
        {'C',"L1I",0.00000},{'C',"L7I",0.00000},{'C',"L6I",0.00000},
        {'S',"L1C",0.00000},
        {'J',"L1C",0.00000},{'J',"L2S",0.00000},{'J',"L5Q",-0.25000},
        {'E',"L1C",0.50000},{'E',"L5Q",-0.25000},{'E',"L7Q",-0.25000},
    };
    hd.phs_num = sizeof(plist)/sizeof(PhsItem);
    memcpy(hd.phs_arr,plist,sizeof(plist));

    //GLO数据
    hd.glo_cnt=10;
    GloFrqItem gdata[]={
        {"R01",1},{"R02",-4},{"R03",5},{"R09",-2},{"R14",-7},
        {"R15",0},{"R16",-1},{"R17",4},{"R18",-3},{"R19",3}
    };
    memcpy(hd.glo_list,gdata,sizeof(gdata));
    hd.glo_bias[0]=71.950;hd.glo_bias[1]=71.950;hd.glo_bias[2]=71.950;
    hd.leap_sec=18;

    //注释
    strcpy(hd.comm[0],"*** Above antenna height is from mark to PHASE CENTER.");
    strcpy(hd.comm[1],"    31     4        1.8000        ANT MEASURE TYPE/HEIGT");
    strcpy(hd.comm[2],"    0.0725    0.0439    0.0091    0.0100    0.0000");
    strcpy(hd.comm[3],"                    BASE STATION");
    hd.comm_cnt=4;

    write_rinex_header(fp,&hd);
    fclose(fp);
    printf("生成out.obs成功，内容与你提供的示例完全一致\n");
    return 0;
}




