Please create an audio file in English in loud voice where you will explain me information written in the attached file in very easy and creative way as I am an intern doctor in Belarus without any kind of experience and I need a very easy explanation to understand this information written in this attached file with 60 pages in it.
cd /tmp/workspace && ls -la; mkdir -p audio-task && python3 -c " import pdfplumber p='/tmp/workspace/attachments/20d4b1b1-c46b-4c16-b214-d74fa00e7680/DOC-20261103-WA0000 (2).pdf' out=open('/tmp/workspace/audio-task/text.txt','w') with pdfplumber.open(p) as pdf: print(len(pdf.pages)) for i,pg in enumerate(pdf.pages): t=pg.extract_text() or '' out.write(f'\n=== PAGE {i+1} ===\n'+t) if i<3: print(i+1,len(t),len(pg.images)) "; wc -c audio-task/text.txt; pip list 2>/dev/null | grep -i -E "tts|pyttsx|gtts|edge|pydub|espeak|torch|piper|soundfile"; which espeak espeak-ng ffmpeg
The file /tmp/workspace/audio-task/text.txt contains text extracted from a 60-page Russian-language Belarus legal document (Instruction on issuing and filling in sick-leave certificates 'листки нетрудоспособности' and 'справки о временной нетрудоспособности', Resolution of MinHealth and MinLabor No. 1/1 of 4 Jan 2018 as amended). Pages are delimited by '=== PAGE n ==='. YOUR JOB: read pages 1 to 30 fully (use read_file with offset/limit in chunks of ~100 lines, or python via execute to print chunks of a few thousand characters at a time; keep going until you have covered all of pages 1-30). Then write a detailed, accurate structured summary IN ENGLISH to /tmp/workspace/audio-task/notes_part1.md. Cover every chapter/section in order, with paragraph (пункт) numbers, and include all concrete rules: who can issue sick leave (which doctors/organizations), who cannot, maximum durations, time limits (days), when a doctor-consultation commission (ВКК) is needed, extension rules, which categories of patients (employees, pregnant, child care, quarantine, sanatorium, prosthetics, foreign citizens, etc.), when sick leave is NOT issued, how it is registered/electronic form, and any numbers/terms. Keep specific numbers exactly right. Aim for about 3000-4000 words. Do not invent anything not in the text. Return as your final message just a short confirmation plus a list of the section headings you covered.
The file /tmp/workspace/audio-task/text.txt contains text extracted from a 60-page Russian-language Belarus legal document (Instruction on issuing and filling in sick-leave certificates 'листки нетрудоспособности' and 'справки о временной нетрудоспособности', Resolution of MinHealth and MinLabor No. 1/1 of 4 Jan 2018 as amended). Pages are delimited by '=== PAGE n ==='. YOUR JOB: read pages 31 to 60 fully (find the line of '=== PAGE 31 ===' with grep, then use read_file with offset/limit in chunks of ~100 lines, or python via execute to print chunks of a few thousand characters at a time; keep going until you have covered all pages 31-60, including the appendices/forms/приложения). Then write a detailed, accurate structured summary IN ENGLISH to /tmp/workspace/audio-task/notes_part2.md. Cover every chapter/section in order, with paragraph (пункт) numbers, and include all concrete rules: durations, time limits (days), ВКК rules, extension, special categories (pregnancy and maternity, child care, quarantine, sanatorium, prosthetics, dispensary, foreign citizens, occupational injuries, etc.), when sick leave is NOT issued, how to fill in the form fields, how to correct mistakes, duplicates, lost certificates, electronic form, and what the appendices contain. Keep specific numbers exactly right. Aim for about 3000-4000 words. Do not invent anything not in the text. Return as your final message just a short confirmation plus a list of the section headings you covered.
cd /tmp/workspace/audio-task && timeout 60 python3 -c " from gtts import gTTS gTTS('Hello, this is a test.',lang='en').save('t.mp3') print('ok') " 2>&1 | tail -3; ls -la; python3 -c " import torchaudio;print(torchaudio.list_audio_backends())"; pip list 2>/dev/null | grep -i -E "scipy|numpy|lameenc|pyttsx|soundfile|TTS|kokoro|pocket"
cd /tmp/workspace/audio-task; wc -c text.txt; grep -n "=== PAGE" text.txt | head -70
cd /tmp/workspace/audio-task; wc -c text.txt; grep -n "=== PAGE" text.txt | sed -n '28,62p'
cd /tmp/workspace/audio-task; sed -n '1112,2260p' text.txt | grep -n -E "^(ГЛАВА|Глава|Приложение|ПРИЛОЖЕНИЕ|РАЗДЕЛ|[0-9]+\. )|=== PAGE" | cut -c1-200 | head -150
cd /tmp/workspace/audio-task; grep -n "^ *ГЛАВА" text.txt | head -40
Which topic should I cover in detail first?
Which part should I summarize in detail first?
The file /tmp/workspace/audio-task/text.txt contains text extracted from a 60-page Russian-language Belarus legal document (Instruction on issuing and filling in sick-leave certificates 'листки нетрудоспособности' and 'справки о временной нетрудоспособности', Resolution of MinHealth and MinLabor No. 1/1 of 4 Jan 2018 as amended). Pages are delimited by '=== PAGE n ==='. YOUR JOB: read pages 1 to 30 fully (use python via execute to print chunks of about 8000 characters at a time, or read_file in chunks; keep going until you have covered all of pages 1-30). Then write a detailed, accurate structured summary IN ENGLISH to /tmp/workspace/audio-task/notes_part1.md. Cover every chapter/section in order, with paragraph (пункт) numbers, and include all concrete rules: who can issue sick leave (which doctors/organizations), who cannot, maximum durations, time limits (days), when a doctor-consultation commission (ВКК) is needed, extension rules, categories of patients (employees, pregnant, child care, quarantine, sanatorium, prosthetics, foreign citizens, etc.), when sick leave is NOT issued, how it is registered/electronic form, and any numbers/terms. Keep specific numbers exactly right. Aim for about 3000-4000 words. Do not invent anything not in the text. Return as your final message just a short confirmation plus a list of the section headings you covered.
The file /tmp/workspace/audio-task/text.txt contains text extracted from a 60-page Russian-language Belarus legal document (Instruction on issuing and filling in sick-leave certificates 'листки нетрудоспособности' and 'справки о временной нетрудоспособности', Resolution of MinHealth and MinLabor No. 1/1 of 4 Jan 2018 as amended). Pages are delimited by '=== PAGE n ==='. YOUR JOB: read pages 31 to 60 fully (find where '=== PAGE 31 ===' starts, then use python via execute to print chunks of about 8000 characters at a time, or read_file in chunks; keep going until you have covered all pages 31-60, including appendices/forms/приложения). Then write a detailed, accurate structured summary IN ENGLISH to /tmp/workspace/audio-task/notes_part2.md. Cover every chapter/section in order, with paragraph (пункт) numbers, and include all concrete rules: durations, time limits (days), ВКК rules, extension, special categories (pregnancy and maternity, child care, quarantine, sanatorium, prosthetics, dispensary, foreign citizens, occupational injuries, etc.), when sick leave is NOT issued, how to fill in the form fields, how to correct mistakes, duplicates, lost certificates, electronic form, and what the appendices contain. Keep specific numbers exactly right. Aim for about 3000-4000 words. Do not invent anything not in the text. Return as your final message just a short confirmation plus a list of the section headings you covered.
pip install --user miniaudio lameenc 2>&1 | tail -2
cd /tmp/workspace/audio-task; wc -c text.txt; python3 -c " t=open('text.txt',encoding='utf-8').read() i=t.find('=== PAGE 31 ===') print(i, len(t)) "
cd /tmp/workspace/audio-task && python3 -c " t=open('text.txt',encoding='utf-8').read() i=t.find('=== PAGE 31 ===') print(len(t),i) s=t[i:] open('/tmp/p2.txt','w').write(s) print(len(s)) print(s[:8000]) "
Which topic should I go into in detail first (pages 31–60)? Also, please confirm the file path, since /tmp/workspace/audio-task was not found.
**/text.txt in /tmp
Which topic should I go into in detail first? (Please also re-upload the file or give me the correct path.)
The file /tmp/workspace/audio-task/text.txt contains text extracted from a 60-page Russian-language Belarus legal document (Instruction on issuing and filling in sick-leave certificates 'листки нетрудоспособности' and 'справки о временной нетрудоспособности', Resolution of MinHealth and MinLabor No. 1/1 of 4 Jan 2018 as amended). Pages are delimited by '=== PAGE n ==='. YOUR JOB: read the WHOLE file, pages 1 to 60 (use python via execute to print chunks of about 8000 characters at a time, and keep going until you have covered all 60 pages including appendices). Then write a detailed, accurate structured summary IN ENGLISH to /tmp/workspace/audio-task/notes.md, about 6000 words. Cover every chapter/section in order, with paragraph (пункт) numbers, and include all concrete rules: who can issue sick leave (which doctors/organizations), who cannot, maximum durations, time limits in days, when the doctor-consultation commission (ВКК) is needed, extension rules, categories (employees, pregnancy and maternity, child care, quarantine, sanatorium, prosthetics, dispensary, foreign citizens, occupational injuries), when sick leave is NOT issued, electronic form, how to fill in form fields, corrections, duplicates, lost certificates, and what the appendices contain. Keep specific numbers exactly right. Do not invent anything. Return as final message a short confirmation plus the list of section headings covered.
cd /tmp/workspace/audio-task; wc -c text.txt; python3 -c " t=open('text.txt',encoding='utf-8').read();print(len(t));print(t[:8000])"
**/text.txt in /tmp
/tmp/workspace
Which topic should I go into in detail first (once the file is available)?
cd /tmp/workspace/audio-task && python3 - <<'E' import re t=open('text.txt').read() # remove amendment notes t=re.sub(r'\((?:п\.|пункт|абзац|часть|в ред\.|введ|дополнен|статья|подп|подпункт|глава|приложение|наименование|преамбула|таблица|форма)[^()]*(?:\([^()]*\)[^()]*)*\)','',t) t=re.sub(r'\n(?:Текст данной|редакцией нормативного|информации$)[^\n]*','',t) t=re.sub(r'-{20,}','',t) t=re.sub(r'\n\s*\n+','\n',t) open('clean.txt','w').write(t) print(len(t)) for m in re.finditer(r'\n(ГЛАВА[^\n]*\n[^\n]*|ПРИЛОЖЕНИЕ[^\n]*)',t): print(m.start(),m.group(1)[:100].replace('\n',' | ')) E
cd /tmp/workspace/audio-task && python3 -c " t=open('clean.txt').read();print(t[0:16000])"
cd /tmp/workspace/audio-task && python3 - <<'E' import re t=open('clean.txt').read() out=[] bad=0 for line in t.split('\n'): if re.search('[ÐÑ]',line): try: # decode maximal: mixed lines possible; try whole line l2=line.encode('latin-1').decode('utf-8') line=l2 except Exception: # mixed: decode runs of latin-1 chars def f(m): try: return m.group(0).encode('latin-1').decode('utf-8') except Exception: return m.group(0) line2=re.sub(r'[\u00c0-\u00ff\u0080-\u009f\u0100-\u02ff\u2000-\u20ff]+(?:[ \u00a0]?[\u00c0-\u00ff\u0080-\u009f\u0100-\u02ff\u2000-\u20ff]+)*',f,line) line=line2 out.append(line) t2='\n'.join(out) print(len(re.findall('[ÐÑ]',t2))) open('clean2.txt','w').write(t2) print(t2[16000:17000]) E
cd /tmp/workspace/audio-task && python3 -c " t=open('clean2.txt').read();print(t[17000:41000])"
cd /tmp/workspace/audio-task && python3 -c " t=open('clean2.txt').read();print(t[41000:65500])"
cd /tmp/workspace/audio-task && python3 - <<'E' import re t=open('clean.txt').read() def fix(line): if not re.search('[ÐÑ]',line): return line b=b''.join(c.encode('latin-1') if ord(c)<256 else c.encode('utf-8') for c in line) return b.decode('utf-8',errors='replace') t='\n'.join(fix(l) for l in t.split('\n')) open('clean3.txt','w').write(t) i=t.index('ГЛАВА 6'); i=t.index('ГЛАВА 6',i+10) if t.count('ГЛАВА 6')>1 else i s=t[i:] s=re.sub(r'=== PAGE \d+ ===\n','',s) paras=re.split(r'\n(?=\d+(?:-\d+)?\. )',s) for p in paras: p=p.replace('\n',' ') print(p[:330]); E
~/audio-task/script.txt
## Intro Hello, future doctor! Welcome. Take a deep breath, because today we are going to make a big, scary Belarusian document feel like a bedtime story. The document you sent me is sixty pages long. It is a joint order of the Ministry of Health and the Ministry of Labor and Social Protection of Belarus. It is number one slash one, dated the fourth of January two thousand eighteen, and it has been updated many times, most recently in December two thousand twenty five. Its job is simple. It tells you, the doctor, exactly how to hand out and fill in a piece of paper that every patient in Belarus needs. In Russian it is called "listok netrudosposobnosti". I will call it the sick leave certificate, or the L N for short. Here is the big idea. Think of the sick leave certificate as a boarding pass. Without it, your patient cannot get on the flight called "paid time off". And you, the doctor, are the gate agent. If you stamp it wrong, the passenger gets stuck at the gate. So let us learn how to stamp it right. ## Part one Let us start with the paper itself. There are two documents in this order, and they look like twins. The first is the L N, the sick leave certificate. The second is called a "spravka", a certificate of temporary incapacity. What is the difference? Imagine two tickets. The L N is the golden ticket. It is for people who will get a sickness benefit from the state social insurance fund. The spravka is the silver ticket. It is only a proof that the person was ill. No benefit from the fund comes with it. And here is a rule to remember: if a patient qualifies for both at the same time, you give the golden ticket, the L N. Both papers have two parts. On top there is a small control stub, like the stub of a cinema ticket. The clinic keeps the stub. Below is the main part that goes to the patient. The L N is a protected document, almost like banknotes, so you must never treat it like scrap paper. ## Part two Now, who gets the golden ticket? The order has a long list, so let me tell it as a story of people standing in a queue. First in line are people who work. Employees at their main job. Part timers, but only when they have no main job on the day the illness, pregnancy or childbirth begins. People working under certain civil contracts where state social insurance applies. Also people covered by insurance against workplace accidents and occupational diseases. Next are unemployed people who are registered at the employment office and are doing paid temporary work. Then come women who are going on maternity leave but are not working. For example, a woman whose maternity leave begins within thirty calendar days after her employment contract ended. Or a full time student, or a student who graduated within the last two months. Or women in clinical residency, full time. Or women who are registered as unemployed or are studying on a referral from the employment office. And finally, military personnel and people in similar services, such as police, the investigative committee, and the emergency ministry. They have their own line in the list. Now the silver ticket, the spravka. Who gets it? Here are the main groups. Number one, people who are being called up for military service, or going for a medical exam related to military service. Number two, people on alternative service. Number three, people whose illness started within thirty calendar days after their employment contract ended. Number four, students in secondary, vocational and higher education, clinical residents, and people in retraining, unless they are doing it on their employer's referral. Number five, working age people who do not work, are not disabled, and are not registered as unemployed. Number six, people who are in detention, under arrest, under court ordered compulsory treatment, or under certain types of suspension from work. Number seven, people with disability, when they are ill from the cause of their disability for a long time. I will come back to this one, because it has numbers. And number eight, many care situations, which we will discuss in a moment. ## Part three Where and who can issue it? The golden rule: a state health organization gives the L N or spravka to the patient in person, after you have done the expertise of temporary incapacity. That is the official name for the assessment where you decide, "Yes, this person cannot work right now, and here is for how long." Normally you issue it where the patient lives or works or studies. But what if the patient gets sick far from home and comes to you? Then you need permission from the head of the organization, the deputy, or the chairperson of the V K K. V K K means the doctors' advisory commission. It is a small committee inside each clinic. Think of it as the referee of the clinic. There are exceptions where you do not need permission. Republican hospitals can issue to anyone living in Belarus. Regional hospitals to residents of their region. District hospitals to residents of their district. And departmental clinics to the employees of that department. Also, if the patient is officially attached to your clinic, you can issue regardless of where they live or work. Now some practical habits. Extending or closing the L N in an outpatient setting is done on the last day of the period that the doctor wrote in the box called "release from work". Not before, not after. There are exceptions, like a V K K exam, or if the patient died, or if you close it early because the patient recovered. If the patient comes late to the appointment, the continuation starts from the day of the real visit. And you write the type and dates of the violation of the regime. If a new injury happens during sick leave, you issue a new L N. You issue as many papers as the patient needs for each place of work. But there is a nice rule: if a person works under an employment contract and gets benefit from the fund, they get only one L N, for the main job. Part time jobs get spravkas. When you close the sick leave, ask for the passport or another identity document. If the patient is hospitalized, you can close the outpatient sick leave on the day before admission. Or, if needed, issue and close it up to the end of the stay with the conclusion about work ability marked as zero, which means "continues to be ill". At discharge, you continue it for the rest of the stay. If the patient dies during sick leave, you write the document up to the day of death, including that day, using the medical death certificate. If the patient loses the paper or damages it, you give a duplicate. And do not forget the logbook. Every L N and every spravka that you give out must be recorded in a registration journal at the same moment you give it to the person. In the notes column you write things like the medical record number, the date of the V K K, the violation of regime, alcohol intoxication, and the name or initials of the person who registered it. ## Part four Now, the numbers. Every doctor needs these numbers in their pocket. The first number is ten. A treating doctor uses a personal stamp for periods up to ten calendar days from the start of the case, as I understand the stamp rules. Longer periods go through the V K K. So when you see a patient who is not getting better, think, "Time to call the referee." The second number is one hundred twenty. If sick leave goes beyond one hundred twenty calendar days continuously, then the extension is allowed only with the decision of the M R E K. That is the medical rehabilitation expert commission, the one that decides about disability. For tuberculosis, the limit is one hundred eighty days. The third number is one hundred fifty. If the same illness or related illnesses come back again and again in one calendar year, the limit is one hundred fifty days with breaks. For tuberculosis, two hundred forty days. These limits also cover prosthetics in a hospital. If you send a patient to the M R E K, you keep the L N open until the day when the referral is registered at the M R E K. After that, what you do depends on the M R E K's decision. If they recognize disability with work recommendations, the L N is extended for the whole period of examination and then closed. If they say the person is still not able to work, the L N is closed. If they decide to extend the treatment, you continue the L N like normal. Another number is sixty and ninety, for people with a disability. If a disabled person is ill because of the cause of their disability, and the illness lasts more than sixty days in a row, or ninety days with breaks in a calendar year, then you switch from the L N to a spravka. You close the L N and open the spravka at the same time, and you may do it up to three days before the end of the period. If it spills over to the next year, a new L N starts on the first of January. Here is a small trap. If a patient is able to work and is just sent for a consultation or a council of doctors, even in another city, they do not get an L N for that trip. If a patient is being rehabilitated as an outpatient, there is also no L N. What if the patient is sent abroad, or to a special center, or to speleotherapy, which is treatment in salt caves? Then the V K K of the clinic at the place of residence makes a decision before the patient leaves, and the L N is continued after return, again after a V K K exam. Finally, a human detail. If a patient is discharged from the hospital but cannot get home that same day because it is far away, you extend the L N by one extra day on a separate line and close it. ## Part five Now my favorite part: taking care of someone else. This is where interns get confused, so let me make it a game. Imagine a family. Mom, dad, a toddler, a school child, grandpa, and a person with disability. If someone gets sick, who stays home? Rule one. For a sick child under three years old, or a disabled child under eighteen, or a sick family member, the L N goes to the person who directly takes care of them. Several family members can take turns, and the papers may be issued to different people one after another, for the same case. Rule two. If the mother works part time, from home, or studies, then the golden ticket goes only to her. Other family members get a spravka. Rule three, for children aged up to fourteen. When the child is treated as an outpatient, you can issue the L N from the first day the caregiver needs to be off work, but not earlier than three days before that date. The L N can last up to fourteen days for one case of illness. If the child still needs care after fourteen days, you close the L N and give a spravka. If the child gets a new, unrelated illness, you close the spravka and give a new L N. If a second child in the family gets sick, same thing: close and give a new L N for the second child. And remember the birthday rule. When the child turns fourteen, the paper is closed on that day. If care is still needed, there is a new L N as a primary one, up to a seven day limit. After seven days, a spravka. Rule four. For a sick relative who is fourteen or older, the V K K must decide that care is needed. Then the L N can be given for up to seven calendar days at once, or the spravka after that. Rule five. If the child is in the hospital, the L N is issued and closed on the last day of the period when the child is ill. If several adults are taking turns at the bedside, each gets their own L N, starting from the day they actually start the care. Rule six. Children under ten who go to kindergarten or school, in the time of sanitary and anti epidemic measures, for example contacts of infection like COVID nineteen. The caregiver gets a spravka for the period of self isolation. Rule seven. For a child with disability going to a sanatorium or a rehabilitation center, a parent or relative gets the paper before leaving, by decision of the V K K. Time for travel is written on a separate line. Rule eight. For a person with disability of the first group, in hospital, the paper is issued if the V K K decides they need additional care. And if they are sick or in the hospital, the person who cares for them gets the L N. Notice something? In all these cases the golden question is the same. Who is really taking care? Write the paper for that person. ## Part six Next, two special situations. First, prosthetics. If a patient is in a prosthetic and orthopedic center for a prosthesis, the L N is issued by the V K K decision and on the day of discharge from that center. Second, quarantine and infection control. If a person is suspended from work because of sanitary and anti epidemic measures, the paper is issued by an infectious disease doctor, or the treating doctor, sometimes together with the head of the department or the head of the clinic or the chairperson of the V K K. It covers the whole period of suspension. ## Part seven Now, the big happy chapter: pregnancy and childbirth. This one is wonderfully clear, so let us go through the numbers. At thirty weeks of pregnancy, the woman gets an L N for maternity leave for one hundred twenty six calendar days. That is the standard. If she lives, works, serves, or studies on a radioactive contaminated territory, then the leave starts earlier, at twenty seven weeks, and it lasts one hundred forty six days. If the baby is born before thirty weeks, the leave is counted from the day of birth for one hundred forty days. For women in the radioactive contaminated territory, if the baby is born before twenty seven weeks, it is one hundred sixty days. If a baby is stillborn, the leave is seventy days. If there are complications of pregnancy, childbirth or the postpartum period, which are on an official ministry list, the L N is extended by fourteen calendar days. The decision is made by the V K K of the clinic that provided the care. Adoptive parents and guardians of a child under three months get an L N from the V K K of the hospital where the child was born if the baby goes straight from the hospital. In other cases, the V K K at their place of residence decides. Women on child care leave for a child under three years follow the same rules. ## Part eight Now we get to the "how to write on the paper" part. It is less romantic, but it is where interns usually make mistakes. You use Arabic numbers. You write in Russian or Belarusian. Clearly and legibly. Use violet, blue, or black ink, by hand, or print with a computer. You can use stamps with clichés, but never a stamp of your signature. You use stamps: your personal stamp, the clinic's stamp "For sick leaves and certificates", the stamp of the M R E K, and a few special stamps for centers and sanatoriums. Your personal stamp goes next to your signature. The special clinic stamp goes in the lower left corner of the form when you close the paper. The M R E K stamp goes in the lower right corner after the expert examination. What if you make a mistake? Cross out the wrong information with a single line. Write the correct data above or next to it. Then write on any free field "corrected to this, believe" or "crossed out, do not read". The doctor who made the correction signs and puts the stamp near it. But be careful. A certificate is considered badly filled out, and can be refused, if: there are corrections that are not confirmed; there are more than two corrections; the name does not match the patient's identity document; or required positions are blank. For example if the family name or patronymic is wrong, it is a bad L N. If you issue a duplicate, you write "duplicate" in the special notes and the correct number of the old one. The same for replacing a damaged paper. The back side of the L N is not for you. It is for the employer or the person who pays into the fund. They fill in the average earnings, the number of days, the amounts, and who signs. The head of the department fills in a few boxes too, like the job title and the personnel number. In short, your side is the front. The accountant's side is the back. ## Part nine The end of the document has attachments, which are examples of the forms. They show the blank L N, the blank spravka, and the registration journals for them. These journals are the diary of every paper you gave out. If you ever get inspected, the journal is the first thing they will ask for. ## Outro So let me give you five memory tricks. One. Golden ticket and silver ticket. L N is paid by the fund; spravka is just proof. Two. The referee. When things get long, complicated, or unusual, call the V K K. When it gets longer than the limits of one hundred twenty days, or one hundred fifty with breaks, go to the M R E K. Three. The three day trick. In many cases you can open or close a paper up to three days before the date it begins or ends. Four. The fourteen birthday. A child's L N ends on the day they turn fourteen. Five. Neat paper. One line to cross out, no more than two corrections, a signature and a stamp. Please remember. I explained the most important rules in a simple way, but the original order is the final authority. Before you sign your first real certificate, sit with an experienced colleague and check the exact wording together. Especially for the numbers, because the order has been changed many times, and the newest updates matter. You are going to be a great doctor. Good luck on your first day, and may all your patients get well before the forms get complicated! Thank you for listening.
cd /tmp/workspace/audio-task && python3 - <<'E' s=open('script.txt').read() s=s.replace("It is only a proof that the person was ill. No benefit from the fund comes with it.","It is mostly a proof that the person was ill, and it is used for groups for whom the benefit is not paid through the L N in the usual way.") open('script.txt','w').write(s) E cat > gen.py <<'E' import re,time from gtts import gTTS s=open('/tmp/workspace/audio-task/script.txt').read() secs=[x for x in re.split(r'^## .*\n',s,flags=re.M) if x.strip()] import os os.makedirs('parts',exist_ok=True) for i,sec in enumerate(secs): # split into chunks of <=1500 chars on paragraph paras=[p.strip() for p in sec.split('\n\n') if p.strip()] chunks=[];cur='' for p in paras: if len(cur)+len(p)>1500 and cur: chunks.append(cur);cur=p else: cur=(cur+'\n\n'+p) if cur else p if cur: chunks.append(cur) for j,c in enumerate(chunks): fn=f'parts/{i:02d}_{j:02d}.mp3' if os.path.exists(fn): continue for t in range(4): try: gTTS(c.replace('\n',' '),lang='en',tld='com').save(fn);break except Exception as e: print('retry',fn,e);time.sleep(3) print('done',i,flush=True) print('ALL DONE') E nohup python3 gen.py > gen.log 2>&1 & sleep 60; cat gen.log
cd /tmp/workspace/audio-task && sleep 75; cat gen.log; ls parts | wc -l
cd /tmp/workspace/audio-task && sleep 5; tail -2 gen.log; python3 - <<'E' import miniaudio, numpy as np, lameenc, glob files=sorted(glob.glob('parts/*.mp3')) sr=24000 out=[] for f in files: d=miniaudio.decode_file(f,output_format=miniaudio.SampleFormat.SIGNED16,nchannels=1,sample_rate=sr) a=np.array(d.samples,dtype=np.float32)/32768 out.append(a); out.append(np.zeros(int(sr*0.5),dtype=np.float32)) x=np.concatenate(out) # loudness: normalize RMS to target, soft limit rms=np.sqrt(np.mean(x**2)); x=x*(0.20/rms) x=np.tanh(x*1.5)/np.tanh(1.5) x=x/np.max(np.abs(x))*0.98 print('dur min',len(x)/sr/60,'rms',np.sqrt(np.mean(x**2))) pcm=(x*32767).astype(np.int16) e=lameenc.Encoder();e.set_bit_rate(128);e.set_in_sample_rate(sr);e.set_channels(1);e.set_quality(2) open('/tmp/workspace/audio-task/Sick_Leave_Instruction_Explained_Loud.mp3','wb').write(e.encode(pcm.tobytes())+e.flush()) E ls -la /tmp/workspace/audio-task/*.mp3
pip install --user miniaudio lameenc 2>&1 | tail -3; python3 -c "import miniaudio,lameenc;print('ok')"
cd /tmp/workspace/audio-task && python3 - <<'E' import miniaudio, numpy as np, lameenc, glob files=sorted(glob.glob('parts/*.mp3')) sr=24000 out=[] for f in files: d=miniaudio.decode_file(f,output_format=miniaudio.SampleFormat.SIGNED16,nchannels=1,sample_rate=sr) a=np.array(d.samples,dtype=np.float32)/32768 out.append(a); out.append(np.zeros(int(sr*0.5),dtype=np.float32)) x=np.concatenate(out) rms=np.sqrt(np.mean(x**2)); x=x*(0.20/rms) x=np.tanh(x*1.5)/np.tanh(1.5) x=x/np.max(np.abs(x))*0.98 print('dur min',len(x)/sr/60,'rms',np.sqrt(np.mean(x**2))) pcm=(x*32767).astype(np.int16) e=lameenc.Encoder();e.set_bit_rate(128);e.set_in_sample_rate(sr);e.set_channels(1);e.set_quality(2) open('/tmp/workspace/audio-task/Sick_Leave_Instruction_Explained_Loud.mp3','wb').write(e.encode(pcm.tobytes())+e.flush()) E ls -la /tmp/workspace/audio-task/*.mp3
Sick Leave Instruction Explained Loud
MP3 File · MP3
Now please prepare the colorful handbook pdf in English of this explanation so that I can read it and simultaneously listen to the audio too.
mkdir -p /tmp/workspace/handbook && cd /tmp/workspace/handbook && cat > build.py <<'E' import glob, miniaudio from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.units import mm from reportlab.lib.styles import ParagraphStyle from reportlab.lib.enums import TA_CENTER from reportlab.platypus import (BaseDocTemplate, PageTemplate, Frame, Paragraph, Spacer, Table, TableStyle, PageBreak, KeepTogether, NextPageTemplate) # ---- audio timestamps per section dur={} for f in sorted(glob.glob('/tmp/workspace/audio-task/parts/*.mp3')): i=int(f.split('/')[-1][:2]) info=miniaudio.get_file_info(f) dur[i]=dur.get(i,0)+info.duration+0.5 starts=[];t=0 for i in range(len(dur)): starts.append(t); t+=dur[i] def ts(i): s=int(starts[i]); return f"{s//60:02d}:{s%60:02d}" NAVY=colors.HexColor('#1F2A5A'); GOLD=colors.HexColor('#F2B600'); SILVER=colors.HexColor('#8E9BAE') TEAL=colors.HexColor('#0FA3A3'); CORAL=colors.HexColor('#FF6B6B'); PURPLE=colors.HexColor('#7B4FD6') GREEN=colors.HexColor('#2FB16B'); ORANGE=colors.HexColor('#FF8C42'); PINK=colors.HexColor('#E84F9A'); BLUE=colors.HexColor('#2F80ED') def light(c,a=0.12): return colors.Color(c.red+(1-c.red)*(1-a),c.green+(1-c.green)*(1-a),c.blue+(1-c.blue)*(1-a)) body=ParagraphStyle('b',fontName='Helvetica',fontSize=10.5,leading=15.5,textColor=colors.HexColor('#22263a'),spaceAfter=6) small=ParagraphStyle('s',parent=body,fontSize=9,leading=12,textColor=colors.HexColor('#555a70')) bul=ParagraphStyle('bul',parent=body,leftIndent=14,bulletIndent=2,spaceAfter=3) h_ban=ParagraphStyle('hb',fontName='Helvetica-Bold',fontSize=17,leading=21,textColor=colors.white) h_tag=ParagraphStyle('ht',fontName='Helvetica',fontSize=9,leading=12,textColor=colors.white,alignment=2) h2=ParagraphStyle('h2',fontName='Helvetica-Bold',fontSize=12.5,leading=16,textColor=NAVY,spaceBefore=6,spaceAfter=4) cell=ParagraphStyle('c',parent=body,fontSize=9.5,leading=13,spaceAfter=0) cellb=ParagraphStyle('cb',parent=cell,fontName='Helvetica-Bold',textColor=colors.white) big=ParagraphStyle('big',fontName='Helvetica-Bold',fontSize=30,leading=36,textColor=colors.white,alignment=TA_CENTER) sub=ParagraphStyle('sub',fontName='Helvetica',fontSize=14,leading=19,textColor=colors.white,alignment=TA_CENTER) W=A4[0]-36*mm def P(t,st=body): return Paragraph(t,st) def B(items,color=NAVY): return [Paragraph(x,bul,bulletText='\u25CF') for x in items] def banner(num,title,color,i): t=Table([[P(f'{num} {title}',h_ban),P(f'AUDIO ▶ {ts(i)}',h_tag)]],colWidths=[W*0.78,W*0.22]) t.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),color),('VALIGN',(0,0),(-1,-1),'MIDDLE'), ('LEFTPADDING',(0,0),(-1,-1),10),('RIGHTPADDING',(0,0),(-1,-1),10),('TOPPADDING',(0,0),(-1,-1),9),('BOTTOMPADDING',(0,0),(-1,-1),9), ('ROUNDEDCORNERS',[8,8,8,8])])) return [t,Spacer(1,8)] def box(title,lines,color,icon=''): inner=[P(f'<b>{icon} {title}</b>',ParagraphStyle('x',parent=body,textColor=color,fontSize=11,spaceAfter=3))] for l in lines: inner.append(P(l,ParagraphStyle('y',parent=body,spaceAfter=3))) t=Table([[inner]],colWidths=[W]) t.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),light(color,0.14)),('LINEBEFORE',(0,0),(0,-1),4,color), ('LEFTPADDING',(0,0),(-1,-1),12),('RIGHTPADDING',(0,0),(-1,-1),10),('TOPPADDING',(0,0),(-1,-1),7),('BOTTOMPADDING',(0,0),(-1,-1),6)])) return [t,Spacer(1,8)] def table(rows,widths,head,rowcolors=None,hcolor=NAVY): data=[[P(h,cellb) for h in head]]+[[P(c,cell) for c in r] for r in rows] t=Table(data,colWidths=[W*w for w in widths],repeatRows=1) st=[('BACKGROUND',(0,0),(-1,0),hcolor),('VALIGN',(0,0),(-1,-1),'MIDDLE'), ('GRID',(0,0),(-1,-1),0.5,colors.HexColor('#d5d9e6')), ('TOPPADDING',(0,0),(-1,-1),5),('BOTTOMPADDING',(0,0),(-1,-1),5),('LEFTPADDING',(0,0),(-1,-1),7)] for k in range(1,len(data)): st.append(('BACKGROUND',(0,k),(-1,k),light(hcolor,0.07) if k%2 else colors.white)) t.setStyle(TableStyle(st)); return [t,Spacer(1,9)] def cover(c,d): c.saveState() c.setFillColor(NAVY); c.rect(0,0,A4[0],A4[1],fill=1,stroke=0) cols=[GOLD,CORAL,TEAL,PURPLE,GREEN,ORANGE,PINK,BLUE] for k,col in enumerate(cols): c.setFillColor(col); c.rect(k*A4[0]/8,A4[1]-14*mm,A4[0]/8,14*mm,fill=1,stroke=0) c.rect(k*A4[0]/8,0,A4[0]/8,10*mm,fill=1,stroke=0) c.setFillColor(GOLD); c.circle(A4[0]-45*mm,A4[1]-60*mm,22*mm,fill=1,stroke=0) c.setFillColor(SILVER); c.circle(40*mm,70*mm,14*mm,fill=1,stroke=0) c.setFillColor(CORAL); c.circle(A4[0]-30*mm,55*mm,8*mm,fill=1,stroke=0) c.restoreState() def later(c,d): c.saveState() c.setFillColor(NAVY); c.rect(0,0,A4[0],9*mm,fill=1,stroke=0) c.setFillColor(colors.white); c.setFont('Helvetica',8.5) c.drawString(18*mm,3.2*mm,'Sick Leave in Belarus: the Easy Handbook') c.drawRightString(A4[0]-18*mm,3.2*mm,f'Page {d.page}') c.setFillColor(GOLD); c.rect(0,A4[1]-4*mm,A4[0],4*mm,fill=1,stroke=0) c.restoreState() doc=BaseDocTemplate('/tmp/workspace/handbook/Sick_Leave_Easy_Handbook.pdf',pagesize=A4,leftMargin=18*mm,rightMargin=18*mm,topMargin=16*mm,bottomMargin=16*mm, title='Sick Leave in Belarus: the Easy Handbook',author='Orris') fr=Frame(18*mm,14*mm,W,A4[1]-30*mm,id='f',leftPadding=0,rightPadding=0,topPadding=0,bottomPadding=0) frc=Frame(25*mm,60*mm,A4[0]-50*mm,A4[1]-140*mm,id='c') doc.addPageTemplates([PageTemplate('cover',[frc],onPage=cover),PageTemplate('main',[fr],onPage=later)]) S=[] S+= [Spacer(1,40*mm),P('SICK LEAVE<br/>IN BELARUS',big),Spacer(1,10), P('The easy, colorful handbook for a brand new intern doctor',sub),Spacer(1,22), P('Read along with the audio guide',ParagraphStyle('z',parent=sub,textColor=GOLD,fontName='Helvetica-Bold')),Spacer(1,6), P('Based on Joint Order of the Ministry of Health and the Ministry of Labor and Social Protection of the Republic of Belarus No. 1/1 of 4 January 2018, as amended up to December 2025', ParagraphStyle('zz',parent=sub,fontSize=10,leading=14,textColor=colors.HexColor('#cfd6f5'))), NextPageTemplate('main'),PageBreak()] # How to use S+= banner('','How to use this handbook',NAVY,0) S+= [P('Each chapter has the <b>same title and order</b> as the audio. The tag on the right of every colored banner (for example <b>AUDIO ▶ 03:10</b>) tells you the minute and second where that chapter starts in the audio file. Press play, jump to the time, and read along.')] rows=[[f'{k+1}',n,ts(i)] for k,(n,i) in enumerate([('The two papers: L N and spravka',1),('Who gets which paper',2),('Who can issue it, and the rules of the road',3),('The numbers you must remember',4),('Taking care of someone else',5),('Prosthetics and quarantine',6),('Pregnancy and childbirth',7),('How to fill in the form',8),('The attachments and memory tricks',9)])] S+= table(rows,[0.08,0.74,0.18],['#','Chapter','Audio starts'],hcolor=TEAL) S+= box('Words you will hear a lot',[ '<b>L N</b> (listok netrudosposobnosti): the sick leave certificate. Our "golden ticket".', '<b>Spravka</b>: the certificate of temporary incapacity. Our "silver ticket".', '<b>V K K</b> (vrachebno-konsultatsionnaya komissiya): the doctors\' advisory commission inside each clinic. Our "referee".', '<b>M R E K</b>: the medical rehabilitation expert commission, which decides about disability. Our "high court".', '<b>Expertise of temporary incapacity</b>: your assessment of whether the patient cannot work now and for how long.'],BLUE,'\u2605') S+= box('Big idea',['Think of the L N as a <b>boarding pass</b>. Without it, your patient cannot board the flight called "paid time off". You are the gate agent. Stamp it right and everyone flies.'],GOLD,'\u2708') S+= [PageBreak()] # 1 S+= banner('1','The two papers',GOLD,1) S+= [P('This order contains two look-alike documents. Both have <b>two parts</b>: a small <b>control stub</b> on top (the clinic keeps it, like a cinema ticket stub) and the main certificate below (the patient takes it). The L N is a protected document, almost like banknotes, so never treat it as scrap paper.')] S+= table([ ['Looks like','Golden ticket','Silver ticket'], ['Who it is for','People who get a sickness benefit from the state social insurance fund','Groups for whom the benefit is not paid through the L N in the usual way (see chapter 2)'], ['Main job','Proof of illness plus basis for the benefit','Mostly proof of illness'], ['If both are possible','<b>Give the L N</b>','Not given, the L N wins']], [0.22,0.39,0.39],['','L N','Spravka'],hcolor=NAVY) S+= box('Remember',['Two kinds of paper, one rule: if a patient qualifies for both at the same time, give the <b>golden ticket (L N)</b>.'],GOLD,'\u2605') # 2 S+= banner('2','Who gets which paper',TEAL,2) S+= [P('Picture a queue of people. These are the main groups from the order.',body),P('Golden ticket (L N)',h2)] S+= B(['Employees at their <b>main job</b>.', '<b>Part timers</b>, but only when they have no main job on the day the illness, pregnancy or childbirth begins.', 'People under certain <b>civil law contracts</b> where state social insurance applies.', 'People covered by insurance against <b>workplace accidents and occupational diseases</b>.', 'Unemployed people registered at the employment office who are doing <b>paid temporary work</b>.', 'Women going on <b>maternity leave</b> who are not working, for example: leave starts within 30 calendar days after the contract ended; full time students or graduates within the last two months; clinical residents (full time); women registered as unemployed or studying on an employment office referral.', '<b>Military personnel</b> and similar services (police, investigative committee, emergency ministry and others).']) S+= [Spacer(1,4),P('Silver ticket (spravka)',h2)] S+= table([ ['1','People called up for military service or going for a military related medical exam'], ['2','People on alternative service'], ['3','Illness that started within <b>30 calendar days</b> after the employment contract ended'], ['4','Students (secondary, vocational, higher), clinical residents, people in retraining, unless they study on their employer\'s referral'], ['5','Working age people who do not work, are not disabled and are not registered as unemployed'], ['6','People in detention, under arrest, under court ordered compulsory treatment, or under certain types of suspension from work'], ['7','People with disability who are ill for a long time from the cause of their disability (numbers in chapter 4)'], ['8','Many care situations (chapter 5)']],[0.07,0.93],['#','Group'],hcolor=SILVER) S+= [PageBreak()] # 3 S+= banner('3','Who can issue it, and rules of the road',PURPLE,3) S+= [P('A <b>state health organization</b> gives the L N or spravka to the patient in person, after you have done the <b>expertise of temporary incapacity</b>.')] S+= table([ ['Normal case','At the clinic where the patient lives, works or studies'], ['Patient is far from home','You need permission from the head of the organization, a deputy, or the V K K chairperson'], ['No permission needed','Republican hospitals: anyone living in Belarus. Regional hospitals: residents of the region. District hospitals: residents of the district. Departmental clinics: employees of that department. Also any patient officially <b>attached</b> to your clinic'], ],[0.28,0.72],['Situation','Rule'],hcolor=PURPLE) S+= [P('Practical habits',h2)] S+= B(['<b>Extend or close</b> an outpatient L N on the <b>last day</b> of the period written in the box "release from work". Exceptions: a V K K exam, the death of the patient, or early closing because the patient recovered.', 'Patient came <b>late</b>? Continue from the real day of the visit and write the type and dates of the violation of regime.', 'A <b>new injury</b> during sick leave means a <b>new L N</b>.', 'Issue as many papers as there are workplaces. But an employee getting the fund benefit gets <b>one L N</b> for the main job; part time jobs get spravkas.', 'When closing the paper, ask for a <b>passport</b> or other identity document.', '<b>Hospitalization</b>: close the outpatient paper the day before admission, or issue and close it up to the end of the stay with the conclusion about work ability marked <b>0</b> ("continues to be ill"). At discharge, continue it for the rest of the stay.', 'Patient <b>dies</b> on sick leave: write the paper up to the day of death, including that day, using the medical death certificate.', 'Patient <b>loses or damages</b> the paper: give a <b>duplicate</b>.']) S+= box('Do not forget the logbook',['Every L N and spravka goes into the <b>registration journal</b> at the moment you give it out. In the notes column write things like the medical record number, the V K K date, violation of regime, alcohol intoxication, and who registered it. In an inspection, the journal is the first thing they ask for.'],PURPLE,'\u270D') S+= [PageBreak()] # 4 S+= banner('4','The numbers you must remember',CORAL,4) S+= table([ ['10 days','Doctor\'s personal stamp covers periods up to 10 calendar days from the start of the case (my reading of a hard to read passage). Longer: V K K.'], ['120 days','Continuous sick leave beyond 120 calendar days: extension only with an <b>M R E K</b> decision. Tuberculosis: <b>180</b> days.'], ['150 days','Repeated cases of the same or related illness in one calendar year, with breaks: limit 150 days. Tuberculosis: <b>240</b> days. Includes prosthetics in a hospital.'], ['60 / 90 days','Disabled person ill from the cause of disability: more than 60 days in a row, or 90 days with breaks in a calendar year, then switch from L N to <b>spravka</b>.'], ['3 days','Close the L N and open the spravka at the same time, up to 3 days before the end of the period. If it runs into the next year, a new L N starts on 1 January.']], [0.16,0.84],['Number','What it means'],hcolor=CORAL) S+= [P('Sending a patient to the M R E K',h2)] S+= table([ ['Keep the L N open until','The day the referral is registered at the M R E K'], ['M R E K says: disabled, with work recommendations','L N extended for the whole examination period, then closed'], ['M R E K says: not able to work','L N closed'], ['M R E K extends treatment','Continue the L N as usual']],[0.4,0.6],['Step','What happens'],hcolor=ORANGE) S+= box('Small traps',[ 'A patient who is able to work and is just sent for a <b>consultation or council of doctors</b> (even in another city) gets <b>no L N</b> for that trip.', 'A patient doing <b>outpatient rehabilitation</b> as a person able to work also gets no L N.', 'Sent abroad, to a special center, or to speleotherapy (salt cave treatment)? The V K K at the place of residence decides <b>before departure</b>; the L N continues after return, again after a V K K exam.', 'Discharged but cannot reach home the same day because it is far? Extend by <b>one extra day on a separate line</b> and close.'],CORAL,'\u26A0') S+= [PageBreak()] # 5 S+= banner('5','Taking care of someone else',GREEN,5) S+= [P('Imagine a family: mom, dad, a toddler, a school child, grandpa and a person with disability. When someone gets sick, <b>who stays home?</b> The golden question is always: <b>who is really taking care?</b> Write the paper for that person.')] S+= table([ ['1','Sick child under 3, disabled child under 18, or sick family member','L N to the person who directly cares. Family members can take turns, with papers to different people one after another for the same case.'], ['2','Mother works part time, from home, or studies','Golden ticket only to her. Others get a spravka.'], ['3','Child up to 14, outpatient','L N from the first day care is needed, not earlier than 3 days before that date. Up to <b>14 days</b> per illness; after that a <b>spravka</b>. New unrelated illness or a second sick child: close and give a new L N.'], ['4','Sick relative aged 14 or older','The V K K must decide care is needed. L N for up to <b>7 days</b> at once, then spravka.'], ['5','Child in hospital','L N issued and closed on the last day of the illness period. Adults taking turns at the bedside each get their own L N from the day they really start care.'], ['6','Child under 10 in kindergarten or school during sanitary and anti epidemic measures (e.g. COVID-19 contacts)','Spravka for the period of self isolation.'], ['7','Disabled child going to a sanatorium or rehab center','Parent or relative gets the paper before leaving, by V K K decision. Travel time on a separate line.'], ['8','Person with disability of the first group','Paper if the V K K decides additional care is needed. If that person is sick or in hospital, the caregiver gets the L N.']], [0.06,0.34,0.60],['#','Situation','What you do'],hcolor=GREEN) S+= box('The birthday rule',['A child\'s care paper is <b>closed on the day the child turns 14</b>. If care is still needed, a new L N is issued as a primary one, up to a 7 day limit, then a spravka.'],GREEN,'\u2605') # 6 S+= banner('6','Prosthetics and quarantine',BLUE,6) S+= table([ ['Prosthetics in a prosthetic and orthopedic center','L N issued by V K K decision on the <b>day of discharge</b> from that center.'], ['Suspension from work because of sanitary and anti epidemic measures','Issued by an infectious disease doctor, or the treating doctor (sometimes together with the head of department, head of clinic or V K K chair). Covers the <b>whole period of suspension</b>.']], [0.35,0.65],['Situation','Rule'],hcolor=BLUE) S+= [PageBreak()] # 7 S+= banner('7','Pregnancy and childbirth',PINK,7) S+= [P('This chapter is wonderfully clear. Here are the numbers.')] S+= table([ ['Standard, from <b>30 weeks</b>','<b>126</b> calendar days'], ['Radioactive contaminated territory (lives, works, serves or studies there), from <b>27 weeks</b>','<b>146</b> calendar days'], ['Baby born before 30 weeks (before 27 weeks in contaminated territory)','From the day of birth: <b>140</b> days (<b>160</b> in contaminated territory)'], ['Stillbirth','<b>70</b> days'], ['Complications of pregnancy, birth or postpartum period on the official ministry list','Add <b>14</b> calendar days. V K K of the clinic that gave care decides.']], [0.62,0.38],['Situation','Leave length'],hcolor=PINK) S+= B(['<b>Adoptive parents and guardians</b> of a child under 3 months: L N from the V K K of the hospital where the child was born if the baby goes straight from the hospital. In other cases the V K K at their place of residence decides.', 'Women on <b>child care leave</b> for a child under 3 years follow the same rules.']) S+= [Spacer(1,6)] # 8 S+= banner('8','How to fill in the form',ORANGE,8) S+= table([ ['Numbers and language','Arabic numerals. Russian or Belarusian. Clear and legible.'], ['Ink','Violet, blue or black, by hand or printed by computer. Clich\u00e9 stamps are allowed, <b>except a stamp of your signature</b>.'], ['Stamps','Your personal stamp (next to your signature); the clinic stamp "For sick leaves and certificates" (lower left corner when closing); the M R E K stamp (lower right corner after expert exam); special stamps for centers and sanatoriums.'], ['Back side','Not yours. The employer or fund payer fills in earnings, days and amounts. The department head fills in a few boxes (job title, personnel number).']], [0.25,0.75],['Topic','Rule'],hcolor=ORANGE) S+= box('Made a mistake?',[ '1. Cross out the wrong data with <b>one line</b>.', '2. Write the right data above or beside it.', '3. On a free field write that it is corrected, or "crossed out, do not read".', '4. The doctor who corrected signs and stamps next to it.'],ORANGE,'\u270E') S+= box('When the L N counts as badly filled in',[ '\u2022 Corrections that are not confirmed.', '\u2022 <b>More than two</b> corrections.', '\u2022 Name does not match the identity document (family name, own name, patronymic).', '\u2022 Required positions left blank.'],CORAL,'\u26A0') S+= [P('<b>Duplicates:</b> write "duplicate" and the number of the old paper in the special notes. Same idea when you replace a damaged paper. <b>Short version: your side is the front, the accountant\'s side is the back.</b>')] S+= [PageBreak()] # 9 S+= banner('9','Attachments and memory tricks',TEAL,9) S+= [P('The end of the order has the sample forms: the blank L N, the blank spravka and the registration journals. The journals are the diary of every paper you gave out.')] tricks=[('1','Golden and silver','L N is tied to the fund benefit. Spravka is mostly proof.',GOLD), ('2','The referee','Long or unusual? Call the V K K. Beyond 120 days, or 150 with breaks? Go to the M R E K.',PURPLE), ('3','The three day trick','Many papers can be opened or closed up to 3 days before the date.',TEAL), ('4','The fourteen birthday','A child\'s care L N ends the day they turn 14.',GREEN), ('5','Neat paper','One line to cross out, no more than two corrections, always signature and stamp.',ORANGE)] for n,t_,d_,c_ in tricks: tt=Table([[P(n,ParagraphStyle('n',fontName='Helvetica-Bold',fontSize=22,textColor=colors.white,alignment=TA_CENTER,leading=26)), [P(f'<b>{t_}</b>',ParagraphStyle('tt',parent=body,fontSize=12,textColor=c_,spaceAfter=1)),P(d_,ParagraphStyle('dd',parent=body,spaceAfter=0))]]],colWidths=[W*0.1,W*0.9]) tt.setStyle(TableStyle([('BACKGROUND',(0,0),(0,0),c_),('BACKGROUND',(1,0),(1,0),light(c_,0.12)),('VALIGN',(0,0),(-1,-1),'MIDDLE'), ('TOPPADDING',(0,0),(-1,-1),8),('BOTTOMPADDING',(0,0),(-1,-1),8),('LEFTPADDING',(1,0),(1,0),12)])) S+=[tt,Spacer(1,6)] S+= [Spacer(1,6)] S+= box('Please remember',[ 'This handbook and the audio explain the most important rules in a simple way. The <b>original order is the final authority</b>. It has been amended many times, and the newest changes matter.', 'I read the rules and numbers of chapters 1 to 5 of the order closely. The form filling chapters and the appendices were only skimmed, and some pages of the source file were garbled, so details there are less certain.', 'Before you sign your first real certificate, sit with an experienced colleague or your clinic\'s V K K and check the exact wording together.'],NAVY,'\u2139') S+= [Spacer(1,10),P('You are going to be a great doctor. Good luck on your first day!',ParagraphStyle('end',parent=body,fontName='Helvetica-Bold',fontSize=14,textColor=PINK,alignment=TA_CENTER))] doc.build(S) print([ts(i) for i in range(len(dur))]) E python3 build.py && ls -la Sick_Leave_Easy_Handbook.pdf && python3 -c " import pypdf;print(len(pypdf.PdfReader('Sick_Leave_Easy_Handbook.pdf').pages))"
cd /tmp/workspace/handbook && python3 -c " import pdfplumber with pdfplumber.open('Sick_Leave_Easy_Handbook.pdf') as p: for i in [0,2,5,7]: p.pages[i].to_image(resolution=60).save(f'p{i+1}.png') print('ok')"; ls
cd /tmp/workspace/handbook && python3 -c " import pdfplumber with pdfplumber.open('Sick_Leave_Easy_Handbook.pdf') as p: for i,pg in enumerate(p.pages): ws=pg.extract_words() ymax=max([w['bottom'] for w in ws if w['bottom']<pg.height-30] or [0]) print(i+1,len(ws),round(ymax/pg.height,2),(pg.extract_text() or '')[:60].replace('\n',' | ')) "
cd /tmp/workspace/handbook && python3 - <<'E' import re s=open('build.py').read() s=s.replace("from reportlab.platypus import (","from reportlab.platypus import (CondPageBreak, ") # remove icons s=s.replace("<b>{icon} {title}</b>","<b>{title}</b>") s=s.replace("bulletText='\\u25CF'","bulletText='\\u2022'") s=s.replace("AUDIO ▶ ","AUDIO > ") s=s.replace("(for example <b>AUDIO ▶ 03:10</b>)","(for example <b>AUDIO > 03:10</b>)") s=s.replace("\\u2022 ","- ") # page breaks -> conditional, except cover s=s.replace("NextPageTemplate('main'),PageBreak()]","NextPageTemplate('main'),PageBreak()]") parts=s.split("NextPageTemplate('main'),PageBreak()]") parts[1]=parts[1].replace("S+= [PageBreak()]","S+= [CondPageBreak(70*mm)]") s="NextPageTemplate('main'),PageBreak()]".join(parts) # cond break before each banner s=s.replace("def banner(num,title,color,i):\n","def banner(num,title,color,i):\n pre=[CondPageBreak(60*mm)]\n").replace("return [t,Spacer(1,8)]\ndef box","return pre+[t,Spacer(1,8)]\ndef box") open('build.py','w').write(s) E grep -n "u2605\|u2708\|u270\|u26A0\|u2139\|▶" build.py | head; python3 build.py && python3 -c " import pdfplumber with pdfplumber.open('Sick_Leave_Easy_Handbook.pdf') as p: for i,pg in enumerate(p.pages): ws=pg.extract_words() ymax=max([w['bottom'] for w in ws if w['bottom']<pg.height-30] or [0]) print(i+1,round(ymax/pg.height,2),(pg.extract_text() or '')[:50].replace('\n',' | ')) "
ls -la /tmp/workspace/ /tmp/workspace/handbook /tmp/workspace/audio-task 2>&1 | head -30
~/handbook/build.py
import glob, miniaudio
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER
from reportlab.platypus import (BaseDocTemplate, PageTemplate, Frame, Paragraph, Spacer, Table, TableStyle,
PageBreak, CondPageBreak, NextPageTemplate)
# ---- audio timestamps per section
dur = {}
for f in sorted(glob.glob('/tmp/workspace/audio-task/parts/*.mp3')):
i = int(f.split('/')[-1][:2])
info = miniaudio.get_file_info(f)
dur[i] = dur.get(i, 0) + info.duration + 0.5
starts = []
t = 0
for i in range(len(dur)):
starts.append(t)
t += dur[i]
def ts(i):
s = int(starts[i])
return f"{s//60:02d}:{s%60:02d}"
NAVY = colors.HexColor('#1F2A5A'); GOLD = colors.HexColor('#F2B600'); SILVER = colors.HexColor('#8E9BAE')
TEAL = colors.HexColor('#0FA3A3'); CORAL = colors.HexColor('#FF6B6B'); PURPLE = colors.HexColor('#7B4FD6')
GREEN = colors.HexColor('#2FB16B'); ORANGE = colors.HexColor('#FF8C42'); PINK = colors.HexColor('#E84F9A'); BLUE = colors.HexColor('#2F80ED')
def light(c, a=0.12):
return colors.Color(c.red + (1-c.red)*(1-a), c.green + (1-c.green)*(1-a), c.blue + (1-c.blue)*(1-a))
body = ParagraphStyle('b', fontName='Helvetica', fontSize=10.5, leading=15.5, textColor=colors.HexColor('#22263a'), spaceAfter=6)
bul = ParagraphStyle('bul', parent=body, leftIndent=14, bulletIndent=2, spaceAfter=3)
h_ban = ParagraphStyle('hb', fontName='Helvetica-Bold', fontSize=17, leading=21, textColor=colors.white)
h_tag = ParagraphStyle('ht', fontName='Helvetica-Bold', fontSize=9, leading=12, textColor=colors.white, alignment=2)
h2 = ParagraphStyle('h2', fontName='Helvetica-Bold', fontSize=12.5, leading=16, textColor=NAVY, spaceBefore=6, spaceAfter=4)
cell = ParagraphStyle('c', parent=body, fontSize=9.5, leading=13, spaceAfter=0)
cellb = ParagraphStyle('cb', parent=cell, fontName='Helvetica-Bold', textColor=colors.white)
big = ParagraphStyle('big', fontName='Helvetica-Bold', fontSize=30, leading=36, textColor=colors.white, alignment=TA_CENTER)
sub = ParagraphStyle('sub', fontName='Helvetica', fontSize=14, leading=19, textColor=colors.white, alignment=TA_CENTER)
W = A4[0] - 36*mm
def P(t, st=body):
return Paragraph(t, st)
def B(items):
return [Paragraph(x, bul, bulletText='\u2022') for x in items]
def banner(num, title, color, i):
lab = f'{num} {title}' if num else title
t = Table([[P(lab, h_ban), P(f'AUDIO > {ts(i)}', h_tag)]], colWidths=[W*0.78, W*0.22])
t.setStyle(TableStyle([('BACKGROUND', (0, 0), (-1, -1), color), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('LEFTPADDING', (0, 0), (-1, -1), 10), ('RIGHTPADDING', (0, 0), (-1, -1), 10),
('TOPPADDING', (0, 0), (-1, -1), 9), ('BOTTOMPADDING', (0, 0), (-1, -1), 9)]))
return [CondPageBreak(60*mm), t, Spacer(1, 8)]
def box(title, lines, color):
inner = [P(f'<b>{title}</b>', ParagraphStyle('x', parent=body, textColor=color, fontSize=11, spaceAfter=3))]
for l in lines:
inner.append(P(l, ParagraphStyle('y', parent=body, spaceAfter=3)))
t = Table([[inner]], colWidths=[W])
t.setStyle(TableStyle([('BACKGROUND', (0, 0), (-1, -1), light(color, 0.14)), ('LINEBEFORE', (0, 0), (0, -1), 4, color),
('LEFTPADDING', (0, 0), (-1, -1), 12), ('RIGHTPADDING', (0, 0), (-1, -1), 10),
('TOPPADDING', (0, 0), (-1, -1), 7), ('BOTTOMPADDING', (0, 0), (-1, -1), 6)]))
return [t, Spacer(1, 8)]
def table(rows, widths, head, hcolor=NAVY):
data = [[P(h, cellb) for h in head]] + [[P(c, cell) for c in r] for r in rows]
t = Table(data, colWidths=[W*w for w in widths], repeatRows=1)
st = [('BACKGROUND', (0, 0), (-1, 0), hcolor), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('GRID', (0, 0), (-1, -1), 0.5, colors.HexColor('#d5d9e6')),
('TOPPADDING', (0, 0), (-1, -1), 5), ('BOTTOMPADDING', (0, 0), (-1, -1), 5), ('LEFTPADDING', (0, 0), (-1, -1), 7)]
for k in range(1, len(data)):
st.append(('BACKGROUND', (0, k), (-1, k), light(hcolor, 0.07) if k % 2 else colors.white))
t.setStyle(TableStyle(st))
return [t, Spacer(1, 9)]
def cover(c, d):
c.saveState()
c.setFillColor(NAVY); c.rect(0, 0, A4[0], A4[1], fill=1, stroke=0)
cols = [GOLD, CORAL, TEAL, PURPLE, GREEN, ORANGE, PINK, BLUE]
for k, col in enumerate(cols):
c.setFillColor(col)
c.rect(k*A4[0]/8, A4[1]-14*mm, A4[0]/8, 14*mm, fill=1, stroke=0)
c.rect(k*A4[0]/8, 0, A4[0]/8, 10*mm, fill=1, stroke=0)
c.setFillColor(GOLD); c.circle(A4[0]-45*mm, A4[1]-60*mm, 22*mm, fill=1, stroke=0)
c.setFillColor(SILVER); c.circle(40*mm, 70*mm, 14*mm, fill=1, stroke=0)
c.setFillColor(CORAL); c.circle(A4[0]-30*mm, 55*mm, 8*mm, fill=1, stroke=0)
c.restoreState()
def later(c, d):
c.saveState()
c.setFillColor(NAVY); c.rect(0, 0, A4[0], 9*mm, fill=1, stroke=0)
c.setFillColor(colors.white); c.setFont('Helvetica', 8.5)
c.drawString(18*mm, 3.2*mm, 'Sick Leave in Belarus: the Easy Handbook')
c.drawRightString(A4[0]-18*mm, 3.2*mm, f'Page {d.page}')
c.setFillColor(GOLD); c.rect(0, A4[1]-4*mm, A4[0], 4*mm, fill=1, stroke=0)
c.restoreState()
OUT = '/tmp/workspace/handbook/Sick_Leave_Easy_Handbook.pdf'
doc = BaseDocTemplate(OUT, pagesize=A4, leftMargin=18*mm, rightMargin=18*mm, topMargin=16*mm, bottomMargin=16*mm,
title='Sick Leave in Belarus: the Easy Handbook', author='Orris')
fr = Frame(18*mm, 14*mm, W, A4[1]-30*mm, id='f', leftPadding=0, rightPadding=0, topPadding=0, bottomPadding=0)
frc = Frame(25*mm, 60*mm, A4[0]-50*mm, A4[1]-140*mm, id='c')
doc.addPageTemplates([PageTemplate('cover', [frc], onPage=cover), PageTemplate('main', [fr], onPage=later)])
S = []
S += [Spacer(1, 40*mm), P('SICK LEAVE<br/>IN BELARUS', big), Spacer(1, 10),
P('The easy, colorful handbook for a brand new intern doctor', sub), Spacer(1, 22),
P('Read along with the audio guide', ParagraphStyle('z', parent=sub, textColor=GOLD, fontName='Helvetica-Bold')), Spacer(1, 6),
P('Based on the Joint Order of the Ministry of Health and the Ministry of Labor and Social Protection of the Republic of Belarus No. 1/1 of 4 January 2018, as amended up to December 2025',
ParagraphStyle('zz', parent=sub, fontSize=10, leading=14, textColor=colors.HexColor('#cfd6f5'))),
NextPageTemplate('main'), PageBreak()]
# How to use
S += banner('', 'How to use this handbook', NAVY, 0)
S += [P('Each chapter has the <b>same title and order</b> as the audio. The tag on the right of every colored banner (for example <b>AUDIO > 05:14</b>) tells you the minute and second where that chapter starts in the audio file. Press play, jump to the time, and read along.')]
names = [('The two papers: L N and spravka', 1), ('Who gets which paper', 2), ('Who can issue it, and the rules of the road', 3),
('The numbers you must remember', 4), ('Taking care of someone else', 5), ('Prosthetics and quarantine', 6),
('Pregnancy and childbirth', 7), ('How to fill in the form', 8), ('The attachments and memory tricks', 9)]
S += table([[f'{k+1}', n, ts(i)] for k, (n, i) in enumerate(names)], [0.08, 0.74, 0.18], ['#', 'Chapter', 'Audio starts'], hcolor=TEAL)
S += box('Words you will hear a lot', [
'<b>L N</b> (listok netrudosposobnosti): the sick leave certificate. Our "golden ticket".',
'<b>Spravka</b>: the certificate of temporary incapacity. Our "silver ticket".',
'<b>V K K</b> (vrachebno-konsultatsionnaya komissiya): the doctors\' advisory commission inside each clinic. Our "referee".',
'<b>M R E K</b>: the medical rehabilitation expert commission, which decides about disability. Our "high court".',
'<b>Expertise of temporary incapacity</b>: your assessment of whether the patient cannot work now and for how long.'], BLUE)
S += box('Big idea', ['Think of the L N as a <b>boarding pass</b>. Without it, your patient cannot board the flight called "paid time off". You are the gate agent. Stamp it right and everyone flies.'], GOLD)
# 1
S += banner('1', 'The two papers', GOLD, 1)
S += [P('This order contains two look-alike documents. Both have <b>two parts</b>: a small <b>control stub</b> on top (the clinic keeps it, like a cinema ticket stub) and the main certificate below (the patient takes it). The L N is a protected document, almost like banknotes, so never treat it as scrap paper.')]
S += table([
['Who it is for', 'People who get a sickness benefit from the state social insurance fund', 'Groups for whom the benefit is not paid through the L N in the usual way (see chapter 2)'],
['Main job', 'Proof of illness plus basis for the benefit', 'Mostly proof of illness'],
['If both are possible', '<b>Give the L N</b>', 'Not given, the L N wins']],
[0.22, 0.39, 0.39], ['', 'Golden ticket: L N', 'Silver ticket: spravka'], hcolor=NAVY)
S += box('Remember', ['Two kinds of paper, one rule: if a patient qualifies for both at the same time, give the <b>golden ticket (L N)</b>.'], GOLD)
# 2
S += banner('2', 'Who gets which paper', TEAL, 2)
S += [P('Picture a queue of people. These are the main groups from the order.'), P('Golden ticket (L N)', h2)]
S += B(['Employees at their <b>main job</b>.',
'<b>Part timers</b>, but only when they have no main job on the day the illness, pregnancy or childbirth begins.',
'People under certain <b>civil law contracts</b> where state social insurance applies.',
'People covered by insurance against <b>workplace accidents and occupational diseases</b>.',
'Unemployed people registered at the employment office who are doing <b>paid temporary work</b>.',
'Women going on <b>maternity leave</b> who are not working, for example: leave starts within 30 calendar days after the contract ended; full time students or graduates within the last two months; clinical residents (full time); women registered as unemployed or studying on an employment office referral.',
'<b>Military personnel</b> and similar services (police, investigative committee, emergency ministry and others).'])
S += [Spacer(1, 4), P('Silver ticket (spravka)', h2)]
S += table([
['1', 'People called up for military service or going for a military related medical exam'],
['2', 'People on alternative service'],
['3', 'Illness that started within <b>30 calendar days</b> after the employment contract ended'],
['4', 'Students (secondary, vocational, higher), clinical residents, people in retraining, unless they study on their employer\'s referral'],
['5', 'Working age people who do not work, are not disabled and are not registered as unemployed'],
['6', 'People in detention, under arrest, under court ordered compulsory treatment, or under certain types of suspension from work'],
['7', 'People with disability who are ill for a long time from the cause of their disability (numbers in chapter 4)'],
['8', 'Many care situations (chapter 5)']], [0.07, 0.93], ['#', 'Group'], hcolor=SILVER)
# 3
S += banner('3', 'Who can issue it, and rules of the road', PURPLE, 3)
S += [P('A <b>state health organization</b> gives the L N or spravka to the patient in person, after you have done the <b>expertise of temporary incapacity</b>.')]
S += table([
['Normal case', 'At the clinic where the patient lives, works or studies'],
['Patient is far from home', 'You need permission from the head of the organization, a deputy, or the V K K chairperson'],
['No permission needed', 'Republican hospitals: anyone living in Belarus. Regional hospitals: residents of the region. District hospitals: residents of the district. Departmental clinics: employees of that department. Also any patient officially <b>attached</b> to your clinic']],
[0.28, 0.72], ['Situation', 'Rule'], hcolor=PURPLE)
S += [P('Practical habits', h2)]
S += B(['<b>Extend or close</b> an outpatient L N on the <b>last day</b> of the period written in the box "release from work". Exceptions: a V K K exam, the death of the patient, or early closing because the patient recovered.',
'Patient came <b>late</b>? Continue from the real day of the visit and write the type and dates of the violation of regime.',
'A <b>new injury</b> during sick leave means a <b>new L N</b>.',
'Issue as many papers as there are workplaces. But an employee getting the fund benefit gets <b>one L N</b> for the main job; part time jobs get spravkas.',
'When closing the paper, ask for a <b>passport</b> or other identity document.',
'<b>Hospitalization</b>: close the outpatient paper the day before admission, or issue and close it up to the end of the stay with the conclusion about work ability marked <b>0</b> ("continues to be ill"). At discharge, continue it for the rest of the stay.',
'Patient <b>dies</b> on sick leave: write the paper up to the day of death, including that day, using the medical death certificate.',
'Patient <b>loses or damages</b> the paper: give a <b>duplicate</b>.'])
S += box('Do not forget the logbook', ['Every L N and spravka goes into the <b>registration journal</b> at the moment you give it out. In the notes column write things like the medical record number, the V K K date, violation of regime, alcohol intoxication, and who registered it. In an inspection, the journal is the first thing they ask for.'], PURPLE)
# 4
S += banner('4', 'The numbers you must remember', CORAL, 4)
S += table([
['10 days', 'Doctor\'s personal stamp covers periods up to 10 calendar days from the start of the case (my reading of a hard to read passage). Longer: V K K.'],
['120 days', 'Continuous sick leave beyond 120 calendar days: extension only with an <b>M R E K</b> decision. Tuberculosis: <b>180</b> days.'],
['150 days', 'Repeated cases of the same or related illness in one calendar year, with breaks: limit 150 days. Tuberculosis: <b>240</b> days. Includes prosthetics in a hospital.'],
['60 / 90 days', 'Disabled person ill from the cause of disability: more than 60 days in a row, or 90 days with breaks in a calendar year, then switch from L N to <b>spravka</b>.'],
['3 days', 'Close the L N and open the spravka at the same time, up to 3 days before the end of the period. If it runs into the next year, a new L N starts on 1 January.']],
[0.16, 0.84], ['Number', 'What it means'], hcolor=CORAL)
S += [P('Sending a patient to the M R E K', h2)]
S += table([
['Keep the L N open until', 'The day the referral is registered at the M R E K'],
['M R E K says: disabled, with work recommendations', 'L N extended for the whole examination period, then closed'],
['M R E K says: not able to work', 'L N closed'],
['M R E K extends treatment', 'Continue the L N as usual']], [0.4, 0.6], ['Step', 'What happens'], hcolor=ORANGE)
S += box('Small traps', [
'A patient who is able to work and is just sent for a <b>consultation or council of doctors</b> (even in another city) gets <b>no L N</b> for that trip.',
'A patient doing <b>outpatient rehabilitation</b> as a person able to work also gets no L N.',
'Sent abroad, to a special center, or to speleotherapy (salt cave treatment)? The V K K at the place of residence decides <b>before departure</b>; the L N continues after return, again after a V K K exam.',
'Discharged but cannot reach home the same day because it is far? Extend by <b>one extra day on a separate line</b> and close.'], CORAL)
# 5
S += banner('5', 'Taking care of someone else', GREEN, 5)
S += [P('Imagine a family: mom, dad, a toddler, a school child, grandpa and a person with disability. When someone gets sick, <b>who stays home?</b> The golden question is always: <b>who is really taking care?</b> Write the paper for that person.')]
S += table([
['1', 'Sick child under 3, disabled child under 18, or sick family member', 'L N to the person who directly cares. Family members can take turns, with papers to different people one after another for the same case.'],
['2', 'Mother works part time, from home, or studies', 'Golden ticket only to her. Others get a spravka.'],
['3', 'Child up to 14, outpatient', 'L N from the first day care is needed, not earlier than 3 days before that date. Up to <b>14 days</b> per illness; after that a <b>spravka</b>. New unrelated illness or a second sick child: close and give a new L N.'],
['4', 'Sick relative aged 14 or older', 'The V K K must decide care is needed. L N for up to <b>7 days</b> at once, then spravka.'],
['5', 'Child in hospital', 'L N issued and closed on the last day of the illness period. Adults taking turns at the bedside each get their own L N from the day they really start care.'],
['6', 'Child under 10 in kindergarten or school during sanitary and anti epidemic measures (e.g. COVID-19 contacts)', 'Spravka for the period of self isolation.'],
['7', 'Disabled child going to a sanatorium or rehab center', 'Parent or relative gets the paper before leaving, by V K K decision. Travel time on a separate line.'],
['8', 'Person with disability of the first group', 'Paper if the V K K decides additional care is needed. If that person is sick or in hospital, the caregiver gets the L N.']],
[0.06, 0.34, 0.60], ['#', 'Situation', 'What you do'], hcolor=GREEN)
S += box('The birthday rule', ['A child\'s care paper is <b>closed on the day the child turns 14</b>. If care is still needed, a new L N is issued as a primary one, up to a 7 day limit, then a spravka.'], GREEN)
# 6
S += banner('6', 'Prosthetics and quarantine', BLUE, 6)
S += table([
['Prosthetics in a prosthetic and orthopedic center', 'L N issued by V K K decision on the <b>day of discharge</b> from that center.'],
['Suspension from work because of sanitary and anti epidemic measures', 'Issued by an infectious disease doctor, or the treating doctor (sometimes together with the head of department, head of clinic or V K K chair). Covers the <b>whole period of suspension</b>.']],
[0.35, 0.65], ['Situation', 'Rule'], hcolor=BLUE)
# 7
S += banner('7', 'Pregnancy and childbirth', PINK, 7)
S += [P('This chapter is wonderfully clear. Here are the numbers.')]
S += table([
['Standard, from <b>30 weeks</b>', '<b>126</b> calendar days'],
['Radioactive contaminated territory (lives, works, serves or studies there), from <b>27 weeks</b>', '<b>146</b> calendar days'],
['Baby born before 30 weeks (before 27 weeks in contaminated territory)', 'From the day of birth: <b>140</b> days (<b>160</b> in contaminated territory)'],
['Stillbirth', '<b>70</b> days'],
['Complications of pregnancy, birth or postpartum period on the official ministry list', 'Add <b>14</b> calendar days. V K K of the clinic that gave care decides.']],
[0.62, 0.38], ['Situation', 'Leave length'], hcolor=PINK)
S += B(['<b>Adoptive parents and guardians</b> of a child under 3 months: L N from the V K K of the hospital where the child was born if the baby goes straight from the hospital. In other cases the V K K at their place of residence decides.',
'Women on <b>child care leave</b> for a child under 3 years follow the same rules.'])
S += [Spacer(1, 6)]
# 8
S += banner('8', 'How to fill in the form', ORANGE, 8)
S += table([
['Numbers and language', 'Arabic numerals. Russian or Belarusian. Clear and legible.'],
['Ink', 'Violet, blue or black, by hand or printed by computer. Cliche stamps are allowed, <b>except a stamp of your signature</b>.'],
['Stamps', 'Your personal stamp (next to your signature); the clinic stamp "For sick leaves and certificates" (lower left corner when closing); the M R E K stamp (lower right corner after expert exam); special stamps for centers and sanatoriums.'],
['Back side', 'Not yours. The employer or fund payer fills in earnings, days and amounts. The department head fills in a few boxes (job title, personnel number).']],
[0.25, 0.75], ['Topic', 'Rule'], hcolor=ORANGE)
S += box('Made a mistake?', [
'1. Cross out the wrong data with <b>one line</b>.',
'2. Write the right data above or beside it.',
'3. On a free field write that it is corrected, or "crossed out, do not read".',
'4. The doctor who corrected signs and stamps next to it.'], ORANGE)
S += box('When the L N counts as badly filled in', [
'- Corrections that are not confirmed.',
'- <b>More than two</b> corrections.',
'- Name does not match the identity document (family name, own name, patronymic).',
'- Required positions left blank.'], CORAL)
S += [P('<b>Duplicates:</b> write "duplicate" and the number of the old paper in the special notes. Same idea when you replace a damaged paper. <b>Short version: your side is the front, the accountant\'s side is the back.</b>')]
# 9
S += banner('9', 'Attachments and memory tricks', TEAL, 9)
S += [P('The end of the order has the sample forms: the blank L N, the blank spravka and the registration journals. The journals are the diary of every paper you gave out. The five memory tricks start in the audio at <b>%s</b>.' % ts(10))]
tricks = [('1', 'Golden and silver', 'L N is tied to the fund benefit. Spravka is mostly proof.', GOLD),
('2', 'The referee', 'Long or unusual? Call the V K K. Beyond 120 days, or 150 with breaks? Go to the M R E K.', PURPLE),
('3', 'The three day trick', 'Many papers can be opened or closed up to 3 days before the date.', TEAL),
('4', 'The fourteen birthday', 'A child\'s care L N ends the day they turn 14.', GREEN),
('5', 'Neat paper', 'One line to cross out, no more than two corrections, always signature and stamp.', ORANGE)]
for n, t_, d_, c_ in tricks:
tt = Table([[P(n, ParagraphStyle('n', fontName='Helvetica-Bold', fontSize=22, textColor=colors.white, alignment=TA_CENTER, leading=26)),
[P(f'<b>{t_}</b>', ParagraphStyle('tt', parent=body, fontSize=12, textColor=c_, spaceAfter=1)),
P(d_, ParagraphStyle('dd', parent=body, spaceAfter=0))]]], colWidths=[W*0.1, W*0.9])
tt.setStyle(TableStyle([('BACKGROUND', (0, 0), (0, 0), c_), ('BACKGROUND', (1, 0), (1, 0), light(c_, 0.12)),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), ('TOPPADDING', (0, 0), (-1, -1), 8),
('BOTTOMPADDING', (0, 0), (-1, -1), 8), ('LEFTPADDING', (1, 0), (1, 0), 12)]))
S += [tt, Spacer(1, 6)]
S += [Spacer(1, 6)]
S += box('Please remember', [
'This handbook and the audio explain the most important rules in a simple way. The <b>original order is the final authority</b>. It has been amended many times, and the newest changes matter.',
'I read the rules and numbers of chapters 1 to 5 of the order closely. The form filling chapters and the appendices were only skimmed, and some pages of the source file were garbled, so details there are less certain.',
'Before you sign your first real certificate, sit with an experienced colleague or your clinic\'s V K K and check the exact wording together.'], NAVY)
S += [Spacer(1, 10), P('You are going to be a great doctor. Good luck on your first day!',
ParagraphStyle('end', parent=body, fontName='Helvetica-Bold', fontSize=14, textColor=PINK, alignment=TA_CENTER))]
doc.build(S)
print([ts(i) for i in range(len(dur))])
cd /tmp/workspace/handbook && python3 build.py && python3 -c " import pdfplumber with pdfplumber.open('Sick_Leave_Easy_Handbook.pdf') as p: print(len(p.pages)) for i,pg in enumerate(p.pages): ws=pg.extract_words() ymax=max([w['bottom'] for w in ws if w['bottom']<pg.height-30] or [0]) print(i+1,round(ymax/pg.height,2),(pg.extract_text() or '')[:50].replace('\n',' | ')) "; ls -la /tmp/workspace/handbook
pip install --user miniaudio 2>&1 | tail -1; cd /tmp/workspace/handbook && python3 build.py && python3 -c " import pdfplumber with pdfplumber.open('Sick_Leave_Easy_Handbook.pdf') as p: print(len(p.pages)) for i,pg in enumerate(p.pages): ws=pg.extract_words() ymax=max([w['bottom'] for w in ws if w['bottom']<pg.height-30] or [0]) print(i+1,round(ymax/pg.height,2),(pg.extract_text() or '')[:50].replace('\n',' | ')) "; ls -la /tmp/workspace/handbook
Sick Leave Easy Handbook
PDF Document · PDF
Sick Leave Instruction Explained Loud
MP3 File · MP3
| Chapter | Audio starts |
|---|---|
| Intro and how to use | 00:00 |
| 1. The two papers (L N and spravka) | 01:18 |
| 2. Who gets which paper | 02:31 |
| 3. Who can issue it, and the rules of the road | 05:14 |
| 4. The numbers you must remember | 08:45 |
| 5. Taking care of someone else | 12:04 |
| 6. Prosthetics and quarantine | 15:35 |
| 7. Pregnancy and childbirth | 16:19 |
| 8. How to fill in the form | 17:56 |
| 9. Attachments (20:20) and the five memory tricks (20:42) | 20:20 |